Index: applications/editors/josm/plugins/MicrosoftStreetside/.classpath
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/.classpath	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/.classpath	(revision 34317)
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry including="data/**|images/**|LICENSE|LICENSE_*" kind="src" path=""/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry including="**/*.po" kind="src" path="poSrc"/>
+	<classpathentry kind="src" path="test/data"/>
+	<classpathentry kind="src" path="test/unit"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
+	<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
Index: applications/editors/josm/plugins/MicrosoftStreetside/.project
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/.project	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/.project	(revision 34317)
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>MicrosoftStreetside</name>
+	<comment>Project MicrosoftStreetside created by Buildship.</comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.sonarlint.eclipse.core.sonarlintBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>ch.acanda.eclipse.pmd.builder.PMDBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
+	</natures>
+</projectDescription>
Index: applications/editors/josm/plugins/MicrosoftStreetside/.settings/org.eclipse.buildship.core.prefs
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/.settings/org.eclipse.buildship.core.prefs	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/.settings/org.eclipse.buildship.core.prefs	(revision 34317)
@@ -0,0 +1,2 @@
+connection.project.dir=
+eclipse.preferences.version=1
Index: applications/editors/josm/plugins/MicrosoftStreetside/GPL-v3.0.md
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/GPL-v3.0.md	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/GPL-v3.0.md	(revision 34317)
@@ -0,0 +1,675 @@
+### GNU GENERAL PUBLIC LICENSE
+
+Version 3, 29 June 2007
+
+Copyright (C) 2007 Free Software Foundation, Inc.
+<http://fsf.org/>
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+### Preamble
+
+The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom
+to share and change all versions of a program--to make sure it remains
+free software for all its users. We, the Free Software Foundation, use
+the GNU General Public License for most of our software; it applies
+also to any other work released this way by its authors. You can apply
+it to your programs, too.
+
+When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you
+have certain responsibilities if you distribute copies of the
+software, or if you modify it: responsibilities to respect the freedom
+of others.
+
+For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the
+manufacturer can do so. This is fundamentally incompatible with the
+aim of protecting users' freedom to change the software. The
+systematic pattern of such abuse occurs in the area of products for
+individuals to use, which is precisely where it is most unacceptable.
+Therefore, we have designed this version of the GPL to prohibit the
+practice for those products. If such problems arise substantially in
+other domains, we stand ready to extend this provision to those
+domains in future versions of the GPL, as needed to protect the
+freedom of users.
+
+Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish
+to avoid the special danger that patents applied to a free program
+could make it effectively proprietary. To prevent this, the GPL
+assures that patents cannot be used to render the program non-free.
+
+The precise terms and conditions for copying, distribution and
+modification follow.
+
+### TERMS AND CONDITIONS
+
+#### 0. Definitions.
+
+"This License" refers to version 3 of the GNU General Public License.
+
+"Copyright" also means copyright-like laws that apply to other kinds
+of works, such as semiconductor masks.
+
+"The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of
+an exact copy. The resulting work is called a "modified version" of
+the earlier work or a work "based on" the earlier work.
+
+A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user
+through a computer network, with no transfer of a copy, is not
+conveying.
+
+An interactive user interface displays "Appropriate Legal Notices" to
+the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+#### 1. Source Code.
+
+The "source code" for a work means the preferred form of the work for
+making modifications to it. "Object code" means any non-source form of
+a work.
+
+A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+The Corresponding Source need not include anything that users can
+regenerate automatically from other parts of the Corresponding Source.
+
+The Corresponding Source for a work in source code form is that same
+work.
+
+#### 2. Basic Permissions.
+
+All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+You may make, run and propagate covered works that you do not convey,
+without conditions so long as your license otherwise remains in force.
+You may convey covered works to others for the sole purpose of having
+them make modifications exclusively for you, or provide you with
+facilities for running those works, provided that you comply with the
+terms of this License in conveying all material for which you do not
+control copyright. Those thus making or running the covered works for
+you must do so exclusively on your behalf, under your direction and
+control, on terms that prohibit them from making any copies of your
+copyrighted material outside their relationship with you.
+
+Conveying under any other circumstances is permitted solely under the
+conditions stated below. Sublicensing is not allowed; section 10 makes
+it unnecessary.
+
+#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such
+circumvention is effected by exercising rights under this License with
+respect to the covered work, and you disclaim any intention to limit
+operation or modification of the work as a means of enforcing, against
+the work's users, your or third parties' legal rights to forbid
+circumvention of technological measures.
+
+#### 4. Conveying Verbatim Copies.
+
+You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+#### 5. Conveying Modified Source Versions.
+
+You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these
+conditions:
+
+-   a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+-   b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under
+    section 7. This requirement modifies the requirement in section 4
+    to "keep intact all notices".
+-   c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy. This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged. This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+-   d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+#### 6. Conveying Non-Source Forms.
+
+You may convey a covered work in object code form under the terms of
+sections 4 and 5, provided that you also convey the machine-readable
+Corresponding Source under the terms of this License, in one of these
+ways:
+
+-   a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+-   b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the Corresponding
+    Source from a network server at no charge.
+-   c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source. This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+-   d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge. You need not require recipients to copy the
+    Corresponding Source along with the object code. If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source. Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+-   e) Convey the object code using peer-to-peer transmission,
+    provided you inform other peers where the object code and
+    Corresponding Source of the work are being offered to the general
+    public at no charge under subsection 6d.
+
+A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal,
+family, or household purposes, or (2) anything designed or sold for
+incorporation into a dwelling. In determining whether a product is a
+consumer product, doubtful cases shall be resolved in favor of
+coverage. For a particular product received by a particular user,
+"normally used" refers to a typical or common use of that class of
+product, regardless of the status of the particular user or of the way
+in which the particular user actually uses, or expects or is expected
+to use, the product. A product is a consumer product regardless of
+whether the product has substantial commercial, industrial or
+non-consumer uses, unless such uses represent the only significant
+mode of use of the product.
+
+"Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to
+install and execute modified versions of a covered work in that User
+Product from a modified version of its Corresponding Source. The
+information must suffice to ensure that the continued functioning of
+the modified object code is in no case prevented or interfered with
+solely because modification has been made.
+
+If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or
+updates for a work that has been modified or installed by the
+recipient, or for the User Product in which it has been modified or
+installed. Access to a network may be denied when the modification
+itself materially and adversely affects the operation of the network
+or violates the rules and protocols for communication across the
+network.
+
+Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+#### 7. Additional Terms.
+
+"Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders
+of that material) supplement the terms of this License with terms:
+
+-   a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+-   b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+-   c) Prohibiting misrepresentation of the origin of that material,
+    or requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+-   d) Limiting the use for publicity purposes of names of licensors
+    or authors of the material; or
+-   e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+-   f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions
+    of it) with contractual assumptions of liability to the recipient,
+    for any liability that these contractual assumptions directly
+    impose on those licensors and authors.
+
+All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions; the
+above requirements apply either way.
+
+#### 8. Termination.
+
+You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+However, if you cease all violation of this License, then your license
+from a particular copyright holder is reinstated (a) provisionally,
+unless and until the copyright holder explicitly and finally
+terminates your license, and (b) permanently, if the copyright holder
+fails to notify you of the violation by some reasonable means prior to
+60 days after the cessation.
+
+Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+#### 9. Acceptance Not Required for Having Copies.
+
+You are not required to accept this License in order to receive or run
+a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+#### 10. Automatic Licensing of Downstream Recipients.
+
+Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+#### 11. Patents.
+
+A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+A contributor's "essential patent claims" are all patent claims owned
+or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+A patent license is "discriminatory" if it does not include within the
+scope of its coverage, prohibits the exercise of, or is conditioned on
+the non-exercise of one or more of the rights that are specifically
+granted under this License. You may not convey a covered work if you
+are a party to an arrangement with a third party that is in the
+business of distributing software, under which you make payment to the
+third party based on the extent of your activity of conveying the
+work, and under which the third party grants, to any of the parties
+who would receive the covered work from you, a discriminatory patent
+license (a) in connection with copies of the covered work conveyed by
+you (or copies made from those copies), or (b) primarily for and in
+connection with specific products or compilations that contain the
+covered work, unless you entered into that arrangement, or that patent
+license was granted, prior to 28 March 2007.
+
+Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+#### 12. No Surrender of Others' Freedom.
+
+If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under
+this License and any other pertinent obligations, then as a
+consequence you may not convey it at all. For example, if you agree to
+terms that obligate you to collect a royalty for further conveying
+from those to whom you convey the Program, the only way you could
+satisfy both those terms and this License would be to refrain entirely
+from conveying the Program.
+
+#### 13. Use with the GNU Affero General Public License.
+
+Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+#### 14. Revised Versions of this License.
+
+The Free Software Foundation may publish revised and/or new versions
+of the GNU General Public License from time to time. Such new versions
+will be similar in spirit to the present version, but may differ in
+detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies that a certain numbered version of the GNU General Public
+License "or any later version" applies to it, you have the option of
+following the terms and conditions either of that numbered version or
+of any later version published by the Free Software Foundation. If the
+Program does not specify a version number of the GNU General Public
+License, you may choose any version ever published by the Free
+Software Foundation.
+
+If the Program specifies that a proxy can decide which future versions
+of the GNU General Public License can be used, that proxy's public
+statement of acceptance of a version permanently authorizes you to
+choose that version for the Program.
+
+Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+#### 15. Disclaimer of Warranty.
+
+THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
+WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
+DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+#### 16. Limitation of Liability.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR
+CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
+NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
+LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
+TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
+PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+#### 17. Interpretation of Sections 15 and 16.
+
+If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+END OF TERMS AND CONDITIONS
+
+### How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively state
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+        <one line to give the program's name and a brief idea of what it does.>
+        Copyright (C) <year>  <name of author>
+        
+        This program is free software: you can redistribute it and/or modify
+        it under the terms of the GNU General Public License as published by
+        the Free Software Foundation, either version 3 of the License, or
+        (at your option) any later version.
+        
+        This program is distributed in the hope that it will be useful,
+        but WITHOUT ANY WARRANTY; without even the implied warranty of
+        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+        GNU General Public License for more details.
+        
+        You should have received a copy of the GNU General Public License
+        along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper
+mail.
+
+If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+        <program>  Copyright (C) <year>  <name of author>
+        This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+        This is free software, and you are welcome to redistribute it
+        under certain conditions; type `show c' for details.
+
+The hypothetical commands \`show w' and \`show c' should show the
+appropriate parts of the General Public License. Of course, your
+program's commands might be different; for a GUI interface, you would
+use an "about box".
+
+You should also get your employer (if you work as a programmer) or
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. For more information on this, and how to apply and follow
+the GNU GPL, see <http://www.gnu.org/licenses/>.
+
+The GNU General Public License does not permit incorporating your
+program into proprietary programs. If your program is a subroutine
+library, you may consider it more useful to permit linking proprietary
+applications with the library. If this is what you want to do, use the
+GNU Lesser General Public License instead of this License. But first,
+please read <http://www.gnu.org/philosophy/why-not-lgpl.html>.
Index: applications/editors/josm/plugins/MicrosoftStreetside/GPL-v3.0.txt
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/GPL-v3.0.txt	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/GPL-v3.0.txt	(revision 34317)
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
Index: applications/editors/josm/plugins/MicrosoftStreetside/README.md
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/README.md	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/README.md	(revision 34317)
@@ -0,0 +1,43 @@
+Microsoft Streetside JOSM Plugin
+======
+
+The Microsoft JOSM Streetside (https://www.microsoft.com/en-us/maps/streetside) Plugin enables the viewing of Microsoft Streetside 360 degree imagery in the JOSM editor. It is based on the implementation of the Mapillary plugin (https://wiki.openstreetmap.org/wiki/JOSM/Plugins/Mapillary).
+
+Once JOSM is started and the MicrosoftStreetside plugin is selected in the JOSM Preferences, available Streetside imagery can be display within the boundary of the downloaded JOSM area, by selecting Imagery -> Streetside, from the main menu. Once blue bubbles appear on the map signifying Streetside imagery, clicking on a bubble results in the 360 degree imagery being displayed in the 360 degree viewer, which can be undocked and enlarged to allow for better viewing.
+
+## Documentation
+
+You can find out more about how to use the plugin and how it works in the [project Wiki](https://github.com/JOSM/MicrosoftStreetside/wiki).
+
+If you want to know how to configure the plugin, you can look at the [Configuration Wiki page](https://github.com/JOSM/MicrosoftStreetside/wiki/Configuration).
+
+## Building from source
+Checkout the JOSM source, compile it and checkout the plugin source:
+
+    svn co http://svn.openstreetmap.org/applications/editors/josm josm
+    cd josm/core
+    ant clean dist
+    cd ../plugins
+    rm -rf areaselector
+    git clone https://github.com/JOSM/JOSM-areaselector.git areaselector
+    cd areaselector
+    ant clean install
+    
+Now Restart JOSM and activate the MicrosoftStreeside plugin in your preferences. 
+The MicrosoftStreetside menu items will appear in the JOSM main menu after JOSM is
+restarted.
+
+Details about plugin development can be found [in the JOSM wiki](https://josm.openstreetmap.de/wiki/DevelopersGuide/DevelopingPlugins).
+
+## License
+
+This plugin is based on the Mapilary developed by developed and maintained by nokutu (nokutu@openmailbox.org) and extended to display Streetside imagery by Rene Rhodes (renerr18) You can contact Rene on github.
+
+This software is licensed under [GPL v3](https://www.gnu.org/licenses/gpl-3.0.en.html). 
+
+### Third party resources
+
+The MicrosoftStreetside plugin used JavaFX to implement the Streetside 360 degree viewer [JavaFX](https://en.wikipedia.org/wiki/JavaFX), which, while bundled in the Oracle Java SE 1.8, is not an official part of the 
+Java SE 1.8 specification, and may not function properly with alternative JDKs (e.g. OpenJDK is not currently supported). JavaFX is licensed under the same terms as Java SE (http://www.oracle.com/technetwork/java/javase/terms/license/index.html).
+
+The plugin also makes use of the compact Resty libary for communicating with RESTful web services from Java (https://beders.github.io/Resty/Resty/Overview.html). Resty is licensed under the MIT license (https://github.com/go-resty/resty/blob/master/LICENSE).
Index: applications/editors/josm/plugins/MicrosoftStreetside/build.gradle
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/build.gradle	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/build.gradle	(revision 34317)
@@ -0,0 +1,122 @@
+plugins {
+  id "org.sonarqube" version "2.6.2"
+  id "org.kordamp.markdown.convert" version "1.1.0"
+  id 'org.openstreetmap.josm' version "0.4.0"
+  id "com.github.ben-manes.versions" version "0.17.0"
+  id 'com.github.spotbugs' version '1.6.0'
+  id "net.ltgt.errorprone" version "0.0.13"
+
+  id 'eclipse'
+  id 'idea'
+  id 'jacoco'
+  id 'java'
+  id 'pmd'
+}
+
+apply from: 'gradle/tool-config.gradle'
+//apply from: 'gradle/markdown.gradle'
+
+sourceCompatibility = '1.8'
+
+def versionProcess = new ProcessBuilder("git", "describe", "--always", "--dirty").start()
+versionProcess.waitFor()
+if (versionProcess.exitValue() != 0) {
+  logger.error("Could not determine the current version of this JOSM plugin!")
+  version = "‹unknown›"
+} else {
+  version = versionProcess.in.text.trim()
+}
+archivesBaseName = 'MicrosoftStreetside'
+
+repositories {
+  jcenter()
+  mavenCentral()
+}
+
+dependencies {
+  compile 'com.fasterxml.jackson.core:jackson-core:2.2.4'
+  compile 'com.fasterxml.jackson.core:jackson-databind:2.2.4'
+  compile 'com.fasterxml.jackson.core:jackson-annotations:2.2.4'
+  compile 'us.monoid.web:resty:0.3.2'
+  testImplementation ('org.openstreetmap.josm:josm-unittest'){changing=true}
+  testImplementation 'junit:junit:4.12'
+}
+
+sourceSets {
+  main {
+    java {
+      srcDirs = ['src']
+    }
+    po {
+      srcDirs = ['poSrc']
+    }
+    resources {
+      srcDirs = ["$projectDir"]
+      include 'data/**'
+      include 'images/**'
+      include 'LICENSE'
+      include 'LICENSE_*'
+    }
+  }
+  test {
+    java {
+      srcDirs = ['test/unit']
+    }
+    resources{
+      srcDirs = ['test/data']
+    }
+  }
+}
+
+josm {
+  debugPort = 7051
+  manifest {
+  }
+  i18n {
+    //pathTransformer = getGithubPathTransformer('JOSM/Mapillary')
+  }
+}
+
+eclipse {
+  project {
+    name = 'MicrosoftStreetside'
+    comment = josm.manifest.description
+    natures 'org.sonarlint.eclipse.core.sonarlintNature', 'ch.acanda.eclipse.pmd.builder.PMDNature', 'org.eclipse.buildship.core.gradleprojectnature'
+    buildCommand 'org.sonarlint.eclipse.core.sonarlintBuilder'
+    buildCommand 'ch.acanda.eclipse.pmd.builder.PMDBuilder'
+    buildCommand 'org.eclipse.buildship.core.gradleprojectbuilder'
+  }
+}
+eclipseClasspath.dependsOn cleanEclipseClasspath
+eclipseProject.dependsOn cleanEclipseProject
+tasks.eclipse.dependsOn = ['eclipseClasspath', 'eclipseProject']
+
+tasks.withType(JavaCompile) {
+  // Character encoding of Java files
+  options.encoding = 'UTF-8'
+}
+tasks.withType(Javadoc) {
+  failOnError false
+}
+tasks.withType(com.github.spotbugs.SpotBugsTask) {
+  reports {
+    xml.enabled = false
+    html.enabled = true
+  }
+}
+
+import org.gradle.api.tasks.testing.logging.TestLogEvent
+
+test {
+  testLogging {
+    exceptionFormat "full"
+    events TestLogEvent.FAILED, TestLogEvent.SKIPPED
+    showCauses true
+
+    info {
+      events TestLogEvent.STARTED, TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED, TestLogEvent.STANDARD_OUT, TestLogEvent.STANDARD_ERROR
+      showStandardStreams = true
+    }
+  }
+}
+
Index: applications/editors/josm/plugins/MicrosoftStreetside/build.xml
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/build.xml	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/build.xml	(revision 34317)
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--** This is a template build file for a JOSM  plugin.
+**
+** Maintaining versions
+** ====================-->
+<project name="MicrosoftStreetside" default="dist" basedir="." xmlns:ivy="antlib:org.apache.ivy.ant">
+
+	<!-- Configure these properties (replace "..." accordingly).
+	         See https://josm.openstreetmap.de/wiki/DevelopersGuide/DevelopingPlugins
+	     -->
+	<!-- enter the SVN commit message -->
+	<property name="commit.message" value="Commit message" />
+	<!-- enter the *lowest* JOSM version this plugin is currently compatible with -->
+	<property name="plugin.main.version" value="13878" />
+	<property name="plugin.compile.version" value="13878" />
+
+    <property name="plugin.author" value="renerr18" />
+	<property name="plugin.class" value="org.openstreetmap.josm.plugins.streetside.StreetsidePlugin" />
+	<property name="plugin.description" value="View high resolution Microsoft Streetside 360 degree imagery in JOSM." />
+	<property name="plugin.icon" value="images/streetside-logo-white.png" />
+	<property name="plugin.link" value="https://github.com/JOSM/MicrosoftStreetside"/>
+	<property name="plugin.requires" value="apache-commons;apache-http;"/>
+
+	<property name="plugin.canloadatruntime" value="true"/>
+
+	<!-- edit the properties of this plugin in the file `gradle.properties` -->
+	<property file="${basedir}/gradle.properties"/>
+
+	<property name="josm" location="../../core/dist/josm-custom.jar"/>
+	<property name="plugin.dist.dir" value="../../dist"/>
+
+	<!--** include targets that all plugins have in common **-->
+	<import file="../build-common.xml"/>
+
+	<path id="ivy.lib.path" path="ant/ivy-2.4.0.jar" />
+	<taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path" />
+
+	<!-- ** include targets that all plugins have in common ** -->
+	<import file="../build-common.xml" />
+
+	<fileset id="plugin.requires.jars" dir="${plugin.dist.dir}">
+		<include name="apache-commons.jar"/>
+		<include name="apache-http.jar"/>
+	</fileset>
+
+	<target name="pre-compile" depends="fetch_dependencies">
+		<!-- include fetch_dependencies task -->
+	</target>
+
+	<target name="clean_ivy">
+		<delete failonerror="false">
+			<fileset dir="${plugin.lib.dir}">
+				<include name="**/*.jar"/>
+				<exclude name="**/*-custom.jar" />
+			</fileset>
+		</delete>
+	</target>
+
+	<target name="fetch_dependencies" depends="clean_ivy">
+		<echo>fetching dependencies with ivy</echo>
+		<ivy:retrieve pattern="${plugin.lib.dir}/[artifact]-[type].[ext]" conf="default" />
+	</target>
+
+	<target name="install-plugin" depends="clean, dist, install">
+		<echo>Installed areaselector plugin</echo>
+	</target>
+
+	<target name="test-run" depends="install-plugin, runjosm">
+	</target>
+</project>
Index: applications/editors/josm/plugins/MicrosoftStreetside/config/codecov/codecov.yml
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/config/codecov/codecov.yml	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/config/codecov/codecov.yml	(revision 34317)
@@ -0,0 +1,12 @@
+coverage:
+  status:
+    project:
+      default: on
+      model_and_api:
+        target: 95%
+        flags: model_and_api
+flags:
+  model_and_api:
+    paths:
+      - src/org/openstreetmap/josm/plugins/ms-streetside-josm-plugin/utils/api/
+      - src/org/openstreetmap/josm/plugins/ms-streetside-josm-plugin/model/
Index: applications/editors/josm/plugins/MicrosoftStreetside/config/josm/preferences.xml
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/config/josm/preferences.xml	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/config/josm/preferences.xml	(revision 34317)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<preferences xmlns="http://josm.openstreetmap.de/preferences-1.0">
+  <tag key='MicrosoftStreetside.developer' value='true'/>
+</preferences>
Index: applications/editors/josm/plugins/MicrosoftStreetside/config/pmd/ruleset.xml
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/config/pmd/ruleset.xml	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/config/pmd/ruleset.xml	(revision 34317)
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<ruleset name="Ruleset for jms-streetside-josm-plugin"
+    xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
+  <description>
+    This ruleset checks some rules that you should normally follow for the ms-streetside-josm-plugin.
+  </description>
+  <rule ref="rulesets/java/basic.xml"/>
+  <rule ref="rulesets/java/braces.xml">
+    <exclude name="IfStmtsMustUseBraces"/>
+  </rule>
+  <rule ref="rulesets/java/clone.xml"/>
+
+  <rule ref="rulesets/java/controversial.xml/UnnecessaryConstructor"/>
+  <rule ref="rulesets/java/controversial.xml/AssignmentInOperand"/>
+  <rule ref="rulesets/java/controversial.xml/DontImportSun"/>
+  <rule ref="rulesets/java/controversial.xml/SuspiciousOctalEscape"/>
+  <rule ref="rulesets/java/controversial.xml/UnnecessaryParentheses"/>
+
+  <rule ref="rulesets/java/coupling.xml">
+    <exclude name="LoosePackageCoupling" />
+    <exclude name="LawOfDemeter" />
+  </rule>
+  <rule ref="rulesets/java/design.xml">
+    <exclude name="AvoidSynchronizedAtMethodLevel" />
+    <exclude name="ConfusingTernary" />
+  </rule>
+  <rule ref="rulesets/java/empty.xml"/>
+  <rule ref="rulesets/java/finalizers.xml"/>
+  <rule ref="rulesets/java/imports.xml"/>
+  <rule ref="rulesets/java/naming.xml">
+    <exclude name="ShortVariable"/>
+    <exclude name="LongVariable"/>
+    <exclude name="AbstractNaming"/>
+  </rule>
+  <rule ref="rulesets/java/optimizations.xml">
+    <exclude name="LocalVariableCouldBeFinal" />
+    <exclude name="MethodArgumentCouldBeFinal" />
+    <exclude name="AvoidInstantiatingObjectsInLoops" />
+  </rule>
+  <rule ref="rulesets/java/strictexception.xml"/>
+  <rule ref="rulesets/java/strings.xml"/>
+  <rule ref="rulesets/java/sunsecure.xml"/>
+  <rule ref="rulesets/java/typeresolution.xml"/>
+  <rule ref="rulesets/java/unnecessary.xml">
+    <exclude name="UselessParentheses" />
+  </rule>
+  <rule ref="rulesets/java/unusedcode.xml"/>
+</ruleset>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/allclasses-frame.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/allclasses-frame.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/allclasses-frame.html	(revision 34317)
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>All Classes</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
+<script type="text/javascript" src="script.js"></script>
+</head>
+<body>
+<h1 class="bar">All&nbsp;Classes</h1>
+<div class="indexContainer">
+<ul>
+<li><a href="org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside" target="classFrame">StreetsideAbstractImage</a></li>
+</ul>
+</div>
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/allclasses-noframe.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/allclasses-noframe.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/allclasses-noframe.html	(revision 34317)
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>All Classes</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
+<script type="text/javascript" src="script.js"></script>
+</head>
+<body>
+<h1 class="bar">All&nbsp;Classes</h1>
+<div class="indexContainer">
+<ul>
+<li><a href="org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></li>
+</ul>
+</div>
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/constant-values.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/constant-values.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/constant-values.html	(revision 34317)
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>Constant Field Values</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
+<script type="text/javascript" src="script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="Constant Field Values";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="overview-tree.html">Tree</a></li>
+<li><a href="deprecated-list.html">Deprecated</a></li>
+<li><a href="index-files/index-1.html">Index</a></li>
+<li><a href="help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="index.html?constant-values.html" target="_top">Frames</a></li>
+<li><a href="constant-values.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="header">
+<h1 title="Constant Field Values" class="title">Constant Field Values</h1>
+<h2 title="Contents">Contents</h2>
+</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="overview-tree.html">Tree</a></li>
+<li><a href="deprecated-list.html">Deprecated</a></li>
+<li><a href="index-files/index-1.html">Index</a></li>
+<li><a href="help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="index.html?constant-values.html" target="_top">Frames</a></li>
+<li><a href="constant-values.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/deprecated-list.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/deprecated-list.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/deprecated-list.html	(revision 34317)
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>Deprecated List</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
+<script type="text/javascript" src="script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="Deprecated List";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="overview-tree.html">Tree</a></li>
+<li class="navBarCell1Rev">Deprecated</li>
+<li><a href="index-files/index-1.html">Index</a></li>
+<li><a href="help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="index.html?deprecated-list.html" target="_top">Frames</a></li>
+<li><a href="deprecated-list.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="header">
+<h1 title="Deprecated API" class="title">Deprecated API</h1>
+<h2 title="Contents">Contents</h2>
+</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="overview-tree.html">Tree</a></li>
+<li class="navBarCell1Rev">Deprecated</li>
+<li><a href="index-files/index-1.html">Index</a></li>
+<li><a href="help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="index.html?deprecated-list.html" target="_top">Frames</a></li>
+<li><a href="deprecated-list.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/help-doc.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/help-doc.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/help-doc.html	(revision 34317)
@@ -0,0 +1,223 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>API Help</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
+<script type="text/javascript" src="script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="API Help";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="overview-tree.html">Tree</a></li>
+<li><a href="deprecated-list.html">Deprecated</a></li>
+<li><a href="index-files/index-1.html">Index</a></li>
+<li class="navBarCell1Rev">Help</li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="index.html?help-doc.html" target="_top">Frames</a></li>
+<li><a href="help-doc.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="header">
+<h1 class="title">How This API Document Is Organized</h1>
+<div class="subTitle">This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.</div>
+</div>
+<div class="contentContainer">
+<ul class="blockList">
+<li class="blockList">
+<h2>Package</h2>
+<p>Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain six categories:</p>
+<ul>
+<li>Interfaces (italic)</li>
+<li>Classes</li>
+<li>Enums</li>
+<li>Exceptions</li>
+<li>Errors</li>
+<li>Annotation Types</li>
+</ul>
+</li>
+<li class="blockList">
+<h2>Class/Interface</h2>
+<p>Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:</p>
+<ul>
+<li>Class inheritance diagram</li>
+<li>Direct Subclasses</li>
+<li>All Known Subinterfaces</li>
+<li>All Known Implementing Classes</li>
+<li>Class/interface declaration</li>
+<li>Class/interface description</li>
+</ul>
+<ul>
+<li>Nested Class Summary</li>
+<li>Field Summary</li>
+<li>Constructor Summary</li>
+<li>Method Summary</li>
+</ul>
+<ul>
+<li>Field Detail</li>
+<li>Constructor Detail</li>
+<li>Method Detail</li>
+</ul>
+<p>Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.</p>
+</li>
+<li class="blockList">
+<h2>Annotation Type</h2>
+<p>Each annotation type has its own separate page with the following sections:</p>
+<ul>
+<li>Annotation Type declaration</li>
+<li>Annotation Type description</li>
+<li>Required Element Summary</li>
+<li>Optional Element Summary</li>
+<li>Element Detail</li>
+</ul>
+</li>
+<li class="blockList">
+<h2>Enum</h2>
+<p>Each enum has its own separate page with the following sections:</p>
+<ul>
+<li>Enum declaration</li>
+<li>Enum description</li>
+<li>Enum Constant Summary</li>
+<li>Enum Constant Detail</li>
+</ul>
+</li>
+<li class="blockList">
+<h2>Use</h2>
+<p>Each documented package, class and interface has its own Use page.  This page describes what packages, classes, methods, constructors and fields use any part of the given class or package. Given a class or interface A, its Use page includes subclasses of A, fields declared as A, methods that return A, and methods and constructors with parameters of type A.  You can access this page by first going to the package, class or interface, then clicking on the "Use" link in the navigation bar.</p>
+</li>
+<li class="blockList">
+<h2>Tree (Class Hierarchy)</h2>
+<p>There is a <a href="overview-tree.html">Class Hierarchy</a> page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with <code>java.lang.Object</code>. The interfaces do not inherit from <code>java.lang.Object</code>.</p>
+<ul>
+<li>When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.</li>
+<li>When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.</li>
+</ul>
+</li>
+<li class="blockList">
+<h2>Deprecated API</h2>
+<p>The <a href="deprecated-list.html">Deprecated API</a> page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.</p>
+</li>
+<li class="blockList">
+<h2>Index</h2>
+<p>The <a href="index-files/index-1.html">Index</a> contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.</p>
+</li>
+<li class="blockList">
+<h2>Prev/Next</h2>
+<p>These links take you to the next or previous class, interface, package, or related page.</p>
+</li>
+<li class="blockList">
+<h2>Frames/No Frames</h2>
+<p>These links show and hide the HTML frames.  All pages are available with or without frames.</p>
+</li>
+<li class="blockList">
+<h2>All Classes</h2>
+<p>The <a href="allclasses-noframe.html">All Classes</a> link shows all classes and interfaces except non-static nested types.</p>
+</li>
+<li class="blockList">
+<h2>Serialized Form</h2>
+<p>Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.</p>
+</li>
+<li class="blockList">
+<h2>Constant Field Values</h2>
+<p>The <a href="constant-values.html">Constant Field Values</a> page lists the static final fields and their values.</p>
+</li>
+</ul>
+<span class="emphasizedPhrase">This help file applies to API documentation generated using the standard doclet.</span></div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="overview-tree.html">Tree</a></li>
+<li><a href="deprecated-list.html">Deprecated</a></li>
+<li><a href="index-files/index-1.html">Index</a></li>
+<li class="navBarCell1Rev">Help</li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="index.html?help-doc.html" target="_top">Frames</a></li>
+<li><a href="help-doc.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-1.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-1.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-1.html	(revision 34317)
@@ -0,0 +1,167 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>G-Index</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
+<script type="text/javascript" src="../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="G-Index";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev Letter</li>
+<li><a href="index-2.html">Next Letter</a></li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-1.html" target="_top">Frames</a></li>
+<li><a href="index-1.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="contentContainer"><a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;<a name="I:G">
+<!--   -->
+</a>
+<h2 class="title">G</h2>
+<dl>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getCd--">getCd()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Returns the Epoch time when the image was captured.</div>
+</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getDate--">getDate()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Returns the date the picture was taken in DMY format.</div>
+</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getDate-java.lang.String-">getDate(String)</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Returns the date the picture was taken in the given format.</div>
+</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getHe--">getHe()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Returns the original direction towards the image has been taken.</div>
+</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getId--">getId()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getLatLon--">getLatLon()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Returns a LatLon object containing the original coordinates of the object.</div>
+</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getMovingHe--">getMovingHe()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Returns the direction towards the image has been taken.</div>
+</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getMovingLatLon--">getMovingLatLon()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Returns a LatLon object containing the current coordinates of the object.</div>
+</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getSequence--">getSequence()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Returns the sequence which contains this image.</div>
+</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getTempHe--">getTempHe()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Returns the last fixed direction of the object.</div>
+</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getTempLatLon--">getTempLatLon()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Returns the last fixed coordinates of the object.</div>
+</dd>
+</dl>
+<a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev Letter</li>
+<li><a href="index-2.html">Next Letter</a></li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-1.html" target="_top">Frames</a></li>
+<li><a href="index-1.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-2.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-2.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-2.html	(revision 34317)
@@ -0,0 +1,133 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>I-Index</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
+<script type="text/javascript" src="../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="I-Index";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="index-1.html">Prev Letter</a></li>
+<li><a href="index-3.html">Next Letter</a></li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-2.html" target="_top">Frames</a></li>
+<li><a href="index-2.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="contentContainer"><a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;<a name="I:I">
+<!--   -->
+</a>
+<h2 class="title">I</h2>
+<dl>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#isModified--">isModified()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Returns whether the object has been modified or not.</div>
+</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#isVisible--">isVisible()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Returns whether the image is visible on the map or not.</div>
+</dd>
+</dl>
+<a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="index-1.html">Prev Letter</a></li>
+<li><a href="index-3.html">Next Letter</a></li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-2.html" target="_top">Frames</a></li>
+<li><a href="index-2.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-3.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-3.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-3.html	(revision 34317)
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>M-Index</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
+<script type="text/javascript" src="../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="M-Index";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="index-2.html">Prev Letter</a></li>
+<li><a href="index-4.html">Next Letter</a></li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-3.html" target="_top">Frames</a></li>
+<li><a href="index-3.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="contentContainer"><a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;<a name="I:M">
+<!--   -->
+</a>
+<h2 class="title">M</h2>
+<dl>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#move-double-double-">move(double, double)</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Moves the image temporally to another position</div>
+</dd>
+</dl>
+<a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="index-2.html">Prev Letter</a></li>
+<li><a href="index-4.html">Next Letter</a></li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-3.html" target="_top">Frames</a></li>
+<li><a href="index-3.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-4.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-4.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-4.html	(revision 34317)
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>N-Index</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
+<script type="text/javascript" src="../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="N-Index";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="index-3.html">Prev Letter</a></li>
+<li><a href="index-5.html">Next Letter</a></li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-4.html" target="_top">Frames</a></li>
+<li><a href="index-4.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="contentContainer"><a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;<a name="I:N">
+<!--   -->
+</a>
+<h2 class="title">N</h2>
+<dl>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#next--">next()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">If the StreetsideImage belongs to a StreetsideSequence, returns the next
+ image in the sequence.</div>
+</dd>
+</dl>
+<a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="index-3.html">Prev Letter</a></li>
+<li><a href="index-5.html">Next Letter</a></li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-4.html" target="_top">Frames</a></li>
+<li><a href="index-4.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-5.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-5.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-5.html	(revision 34317)
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>O-Index</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
+<script type="text/javascript" src="../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="O-Index";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="index-4.html">Prev Letter</a></li>
+<li><a href="index-6.html">Next Letter</a></li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-5.html" target="_top">Frames</a></li>
+<li><a href="index-5.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="contentContainer"><a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;<a name="I:O">
+<!--   -->
+</a>
+<h2 class="title">O</h2>
+<dl>
+<dt><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">org.openstreetmap.josm.plugins.streetside</a> - package org.openstreetmap.josm.plugins.streetside</dt>
+<dd>
+<div class="block">The main package in which all core-code (so at the moment all code) resides.</div>
+</dd>
+</dl>
+<a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="index-4.html">Prev Letter</a></li>
+<li><a href="index-6.html">Next Letter</a></li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-5.html" target="_top">Frames</a></li>
+<li><a href="index-5.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-6.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-6.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-6.html	(revision 34317)
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>P-Index</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
+<script type="text/javascript" src="../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="P-Index";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="index-5.html">Prev Letter</a></li>
+<li><a href="index-7.html">Next Letter</a></li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-6.html" target="_top">Frames</a></li>
+<li><a href="index-6.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="contentContainer"><a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;<a name="I:P">
+<!--   -->
+</a>
+<h2 class="title">P</h2>
+<dl>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#previous--">previous()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">If the StreetsideImage belongs to a StreetsideSequence, returns the previous
+ image in the sequence.</div>
+</dd>
+</dl>
+<a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="index-5.html">Prev Letter</a></li>
+<li><a href="index-7.html">Next Letter</a></li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-6.html" target="_top">Frames</a></li>
+<li><a href="index-6.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-7.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-7.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-7.html	(revision 34317)
@@ -0,0 +1,152 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>S-Index</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
+<script type="text/javascript" src="../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="S-Index";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="index-6.html">Prev Letter</a></li>
+<li><a href="index-8.html">Next Letter</a></li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-7.html" target="_top">Frames</a></li>
+<li><a href="index-7.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="contentContainer"><a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;<a name="I:S">
+<!--   -->
+</a>
+<h2 class="title">S</h2>
+<dl>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#setCd-long-">setCd(long)</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Sets the Epoch time when the picture was captured.</div>
+</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#setHe-double-">setHe(double)</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#setId-java.lang.String-">setId(String)</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#setLatLon-org.openstreetmap.josm.data.coor.LatLon-">setLatLon(LatLon)</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#setSequence-org.openstreetmap.josm.plugins.streetside.StreetsideSequence-">setSequence(StreetsideSequence)</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Sets the StreetsideSequence object which contains the StreetsideImage.</div>
+</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#setVisible-boolean-">setVisible(boolean)</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Set's whether the image should be visible on the map or not.</div>
+</dd>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#stopMoving--">stopMoving()</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Called when the mouse button is released, meaning that the picture has
+ stopped being dragged, so the temporal values are saved.</div>
+</dd>
+<dt><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside"><span class="typeNameLink">StreetsideAbstractImage</span></a> - Class in <a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">org.openstreetmap.josm.plugins.streetside</a></dt>
+<dd>
+<div class="block">Abstract superclass for all image objects.</div>
+</dd>
+</dl>
+<a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="index-6.html">Prev Letter</a></li>
+<li><a href="index-8.html">Next Letter</a></li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-7.html" target="_top">Frames</a></li>
+<li><a href="index-7.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-8.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-8.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/index-files/index-8.html	(revision 34317)
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>T-Index</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">
+<script type="text/javascript" src="../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="T-Index";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="index-7.html">Prev Letter</a></li>
+<li>Next Letter</li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-8.html" target="_top">Frames</a></li>
+<li><a href="index-8.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="contentContainer"><a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;<a name="I:T">
+<!--   -->
+</a>
+<h2 class="title">T</h2>
+<dl>
+<dt><span class="memberNameLink"><a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#turn-double-">turn(double)</a></span> - Method in class org.openstreetmap.josm.plugins.streetside.<a href="../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></dt>
+<dd>
+<div class="block">Turns the image direction.</div>
+</dd>
+</dl>
+<a href="index-1.html">G</a>&nbsp;<a href="index-2.html">I</a>&nbsp;<a href="index-3.html">M</a>&nbsp;<a href="index-4.html">N</a>&nbsp;<a href="index-5.html">O</a>&nbsp;<a href="index-6.html">P</a>&nbsp;<a href="index-7.html">S</a>&nbsp;<a href="index-8.html">T</a>&nbsp;</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li><a href="../overview-tree.html">Tree</a></li>
+<li><a href="../deprecated-list.html">Deprecated</a></li>
+<li class="navBarCell1Rev">Index</li>
+<li><a href="../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li><a href="index-7.html">Prev Letter</a></li>
+<li>Next Letter</li>
+</ul>
+<ul class="navList">
+<li><a href="../index.html?index-files/index-8.html" target="_top">Frames</a></li>
+<li><a href="index-8.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/index.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/index.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/index.html	(revision 34317)
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>Generated Documentation (Untitled)</title>
+<script type="text/javascript">
+    tmpTargetPage = "" + window.location.search;
+    if (tmpTargetPage != "" && tmpTargetPage != "undefined")
+        tmpTargetPage = tmpTargetPage.substring(1);
+    if (tmpTargetPage.indexOf(":") != -1 || (tmpTargetPage != "" && !validURL(tmpTargetPage)))
+        tmpTargetPage = "undefined";
+    targetPage = tmpTargetPage;
+    function validURL(url) {
+        try {
+            url = decodeURIComponent(url);
+        }
+        catch (error) {
+            return false;
+        }
+        var pos = url.indexOf(".html");
+        if (pos == -1 || pos != url.length - 5)
+            return false;
+        var allowNumber = false;
+        var allowSep = false;
+        var seenDot = false;
+        for (var i = 0; i < url.length - 5; i++) {
+            var ch = url.charAt(i);
+            if ('a' <= ch && ch <= 'z' ||
+                    'A' <= ch && ch <= 'Z' ||
+                    ch == '$' ||
+                    ch == '_' ||
+                    ch.charCodeAt(0) > 127) {
+                allowNumber = true;
+                allowSep = true;
+            } else if ('0' <= ch && ch <= '9'
+                    || ch == '-') {
+                if (!allowNumber)
+                     return false;
+            } else if (ch == '/' || ch == '.') {
+                if (!allowSep)
+                    return false;
+                allowNumber = false;
+                allowSep = false;
+                if (ch == '.')
+                     seenDot = true;
+                if (ch == '/' && seenDot)
+                     return false;
+            } else {
+                return false;
+            }
+        }
+        return true;
+    }
+    function loadFrames() {
+        if (targetPage != "" && targetPage != "undefined")
+             top.classFrame.location = top.targetPage;
+    }
+</script>
+</head>
+<frameset cols="20%,80%" title="Documentation frame" onload="top.loadFrames()">
+<frame src="allclasses-frame.html" name="packageFrame" title="All classes and interfaces (except non-static nested types)">
+<frame src="org/openstreetmap/josm/plugins/streetside/package-summary.html" name="classFrame" title="Package, class and interface descriptions" scrolling="yes">
+<noframes>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<h2>Frame Alert</h2>
+<p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="org/openstreetmap/josm/plugins/streetside/package-summary.html">Non-frame version</a>.</p>
+</noframes>
+</frameset>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html	(revision 34317)
@@ -0,0 +1,715 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>StreetsideAbstractImage</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
+<script type="text/javascript" src="../../../../../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="StreetsideAbstractImage";
+        }
+    }
+    catch(err) {
+    }
+//-->
+var methods = {"i0":10,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10};
+var tabs = {65535:["t0","All Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]};
+var altColor = "altColor";
+var rowColor = "rowColor";
+var tableTab = "tableTab";
+var activeTableTab = "activeTableTab";
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li class="navBarCell1Rev">Class</li>
+<li><a href="class-use/StreetsideAbstractImage.html">Use</a></li>
+<li><a href="package-tree.html">Tree</a></li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-files/index-1.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev&nbsp;Class</li>
+<li>Next&nbsp;Class</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" target="_top">Frames</a></li>
+<li><a href="StreetsideAbstractImage.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<div>
+<ul class="subNavList">
+<li>Summary:&nbsp;</li>
+<li>Nested&nbsp;|&nbsp;</li>
+<li>Field&nbsp;|&nbsp;</li>
+<li>Constr&nbsp;|&nbsp;</li>
+<li><a href="#method.summary">Method</a></li>
+</ul>
+<ul class="subNavList">
+<li>Detail:&nbsp;</li>
+<li>Field&nbsp;|&nbsp;</li>
+<li>Constr&nbsp;|&nbsp;</li>
+<li><a href="#method.detail">Method</a></li>
+</ul>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<!-- ======== START OF CLASS DATA ======== -->
+<div class="header">
+<div class="subTitle">org.openstreetmap.josm.plugins.streetside</div>
+<h2 title="Class StreetsideAbstractImage" class="title">Class StreetsideAbstractImage</h2>
+</div>
+<div class="contentContainer">
+<ul class="inheritance">
+<li>java.lang.Object</li>
+<li>
+<ul class="inheritance">
+<li>org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage</li>
+</ul>
+</li>
+</ul>
+<div class="description">
+<ul class="blockList">
+<li class="blockList">
+<dl>
+<dt>All Implemented Interfaces:</dt>
+<dd>java.lang.Comparable&lt;<a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a>&gt;</dd>
+</dl>
+<hr>
+<br>
+<pre>public abstract class <span class="typeNameLabel">StreetsideAbstractImage</span>
+extends java.lang.Object
+implements java.lang.Comparable&lt;<a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a>&gt;</pre>
+<div class="block">Abstract superclass for all image objects. At the moment there are just 2,
+ <code>StreetsideImportedImage</code> and <code>StreetsideImage</code>.</div>
+<dl>
+<dt><span class="simpleTagLabel">Author:</span></dt>
+<dd>nokutu</dd>
+</dl>
+</li>
+</ul>
+</div>
+<div class="summary">
+<ul class="blockList">
+<li class="blockList">
+<!-- ========== METHOD SUMMARY =========== -->
+<ul class="blockList">
+<li class="blockList"><a name="method.summary">
+<!--   -->
+</a>
+<h3>Method Summary</h3>
+<table class="memberSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
+<caption><span id="t0" class="activeTableTab"><span>All Methods</span><span class="tabEnd">&nbsp;</span></span><span id="t2" class="tableTab"><span><a href="javascript:show(2);">Instance Methods</a></span><span class="tabEnd">&nbsp;</span></span><span id="t4" class="tableTab"><span><a href="javascript:show(8);">Concrete Methods</a></span><span class="tabEnd">&nbsp;</span></span></caption>
+<tr>
+<th class="colFirst" scope="col">Modifier and Type</th>
+<th class="colLast" scope="col">Method and Description</th>
+</tr>
+<tr id="i0" class="altColor">
+<td class="colFirst"><code>long</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getCd--">getCd</a></span>()</code>
+<div class="block">Returns the Epoch time when the image was captured.</div>
+</td>
+</tr>
+<tr id="i1" class="rowColor">
+<td class="colFirst"><code>java.lang.String</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getDate--">getDate</a></span>()</code>
+<div class="block">Returns the date the picture was taken in DMY format.</div>
+</td>
+</tr>
+<tr id="i2" class="altColor">
+<td class="colFirst"><code>java.lang.String</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getDate-java.lang.String-">getDate</a></span>(java.lang.String&nbsp;format)</code>
+<div class="block">Returns the date the picture was taken in the given format.</div>
+</td>
+</tr>
+<tr id="i3" class="rowColor">
+<td class="colFirst"><code>double</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getHe--">getHe</a></span>()</code>
+<div class="block">Returns the original direction towards the image has been taken.</div>
+</td>
+</tr>
+<tr id="i4" class="altColor">
+<td class="colFirst"><code>java.lang.String</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getId--">getId</a></span>()</code>&nbsp;</td>
+</tr>
+<tr id="i5" class="rowColor">
+<td class="colFirst"><code>org.openstreetmap.josm.data.coor.LatLon</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getLatLon--">getLatLon</a></span>()</code>
+<div class="block">Returns a LatLon object containing the original coordinates of the object.</div>
+</td>
+</tr>
+<tr id="i6" class="altColor">
+<td class="colFirst"><code>double</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getMovingHe--">getMovingHe</a></span>()</code>
+<div class="block">Returns the direction towards the image has been taken.</div>
+</td>
+</tr>
+<tr id="i7" class="rowColor">
+<td class="colFirst"><code>org.openstreetmap.josm.data.coor.LatLon</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getMovingLatLon--">getMovingLatLon</a></span>()</code>
+<div class="block">Returns a LatLon object containing the current coordinates of the object.</div>
+</td>
+</tr>
+<tr id="i8" class="altColor">
+<td class="colFirst"><code>org.openstreetmap.josm.plugins.streetside.StreetsideSequence</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getSequence--">getSequence</a></span>()</code>
+<div class="block">Returns the sequence which contains this image.</div>
+</td>
+</tr>
+<tr id="i9" class="rowColor">
+<td class="colFirst"><code>double</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getTempHe--">getTempHe</a></span>()</code>
+<div class="block">Returns the last fixed direction of the object.</div>
+</td>
+</tr>
+<tr id="i10" class="altColor">
+<td class="colFirst"><code>org.openstreetmap.josm.data.coor.LatLon</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#getTempLatLon--">getTempLatLon</a></span>()</code>
+<div class="block">Returns the last fixed coordinates of the object.</div>
+</td>
+</tr>
+<tr id="i11" class="rowColor">
+<td class="colFirst"><code>boolean</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#isModified--">isModified</a></span>()</code>
+<div class="block">Returns whether the object has been modified or not.</div>
+</td>
+</tr>
+<tr id="i12" class="altColor">
+<td class="colFirst"><code>boolean</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#isVisible--">isVisible</a></span>()</code>
+<div class="block">Returns whether the image is visible on the map or not.</div>
+</td>
+</tr>
+<tr id="i13" class="rowColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#move-double-double-">move</a></span>(double&nbsp;x,
+    double&nbsp;y)</code>
+<div class="block">Moves the image temporally to another position</div>
+</td>
+</tr>
+<tr id="i14" class="altColor">
+<td class="colFirst"><code><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#next--">next</a></span>()</code>
+<div class="block">If the StreetsideImage belongs to a StreetsideSequence, returns the next
+ image in the sequence.</div>
+</td>
+</tr>
+<tr id="i15" class="rowColor">
+<td class="colFirst"><code><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#previous--">previous</a></span>()</code>
+<div class="block">If the StreetsideImage belongs to a StreetsideSequence, returns the previous
+ image in the sequence.</div>
+</td>
+</tr>
+<tr id="i16" class="altColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#setCd-long-">setCd</a></span>(long&nbsp;cd)</code>
+<div class="block">Sets the Epoch time when the picture was captured.</div>
+</td>
+</tr>
+<tr id="i17" class="rowColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#setHe-double-">setHe</a></span>(double&nbsp;he)</code>&nbsp;</td>
+</tr>
+<tr id="i18" class="altColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#setId-java.lang.String-">setId</a></span>(java.lang.String&nbsp;id)</code>&nbsp;</td>
+</tr>
+<tr id="i19" class="rowColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#setLatLon-org.openstreetmap.josm.data.coor.LatLon-">setLatLon</a></span>(org.openstreetmap.josm.data.coor.LatLon&nbsp;latLon)</code>&nbsp;</td>
+</tr>
+<tr id="i20" class="altColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#setSequence-org.openstreetmap.josm.plugins.streetside.StreetsideSequence-">setSequence</a></span>(org.openstreetmap.josm.plugins.streetside.StreetsideSequence&nbsp;sequence)</code>
+<div class="block">Sets the StreetsideSequence object which contains the StreetsideImage.</div>
+</td>
+</tr>
+<tr id="i21" class="rowColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#setVisible-boolean-">setVisible</a></span>(boolean&nbsp;visible)</code>
+<div class="block">Set's whether the image should be visible on the map or not.</div>
+</td>
+</tr>
+<tr id="i22" class="altColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#stopMoving--">stopMoving</a></span>()</code>
+<div class="block">Called when the mouse button is released, meaning that the picture has
+ stopped being dragged, so the temporal values are saved.</div>
+</td>
+</tr>
+<tr id="i23" class="rowColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#turn-double-">turn</a></span>(double&nbsp;ca)</code>
+<div class="block">Turns the image direction.</div>
+</td>
+</tr>
+</table>
+<ul class="blockList">
+<li class="blockList"><a name="methods.inherited.from.class.java.lang.Object">
+<!--   -->
+</a>
+<h3>Methods inherited from class&nbsp;java.lang.Object</h3>
+<code>equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</code></li>
+</ul>
+<ul class="blockList">
+<li class="blockList"><a name="methods.inherited.from.class.java.lang.Comparable">
+<!--   -->
+</a>
+<h3>Methods inherited from interface&nbsp;java.lang.Comparable</h3>
+<code>compareTo</code></li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+<div class="details">
+<ul class="blockList">
+<li class="blockList">
+<!-- ============ METHOD DETAIL ========== -->
+<ul class="blockList">
+<li class="blockList"><a name="method.detail">
+<!--   -->
+</a>
+<h3>Method Detail</h3>
+<a name="getId--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>getId</h4>
+<pre>public&nbsp;java.lang.String&nbsp;getId()</pre>
+<dl>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>the id</dd>
+</dl>
+</li>
+</ul>
+<a name="setId-java.lang.String-">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>setId</h4>
+<pre>public&nbsp;void&nbsp;setId(java.lang.String&nbsp;id)</pre>
+<dl>
+<dt><span class="paramLabel">Parameters:</span></dt>
+<dd><code>id</code> - the id to set</dd>
+</dl>
+</li>
+</ul>
+<a name="getHe--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>getHe</h4>
+<pre>public&nbsp;double&nbsp;getHe()</pre>
+<div class="block">Returns the original direction towards the image has been taken.</div>
+<dl>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>The direction of the image (0 means north and goes clockwise).</dd>
+</dl>
+</li>
+</ul>
+<a name="getCd--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>getCd</h4>
+<pre>public&nbsp;long&nbsp;getCd()</pre>
+<div class="block">Returns the Epoch time when the image was captured.</div>
+<dl>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>The long containing the Epoch time when the image was captured.</dd>
+</dl>
+</li>
+</ul>
+<a name="getDate--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>getDate</h4>
+<pre>public&nbsp;java.lang.String&nbsp;getDate()</pre>
+<div class="block">Returns the date the picture was taken in DMY format.</div>
+<dl>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>A String object containing the date when the picture was taken.</dd>
+</dl>
+</li>
+</ul>
+<a name="getDate-java.lang.String-">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>getDate</h4>
+<pre>public&nbsp;java.lang.String&nbsp;getDate(java.lang.String&nbsp;format)</pre>
+<div class="block">Returns the date the picture was taken in the given format.</div>
+<dl>
+<dt><span class="paramLabel">Parameters:</span></dt>
+<dd><code>format</code> - Format of the date. See <code>SimpleDateFormat</code>.</dd>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>A String containing the date the picture was taken using the given
+         format.</dd>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code>java.lang.NullPointerException</code> - if parameter format is <code>null</code></dd>
+</dl>
+</li>
+</ul>
+<a name="getLatLon--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>getLatLon</h4>
+<pre>public&nbsp;org.openstreetmap.josm.data.coor.LatLon&nbsp;getLatLon()</pre>
+<div class="block">Returns a LatLon object containing the original coordinates of the object.</div>
+<dl>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>The LatLon object with the position of the object.</dd>
+</dl>
+</li>
+</ul>
+<a name="getMovingHe--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>getMovingHe</h4>
+<pre>public&nbsp;double&nbsp;getMovingHe()</pre>
+<div class="block">Returns the direction towards the image has been taken.</div>
+<dl>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>The direction of the image (0 means north and goes clockwise).</dd>
+</dl>
+</li>
+</ul>
+<a name="getMovingLatLon--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>getMovingLatLon</h4>
+<pre>public&nbsp;org.openstreetmap.josm.data.coor.LatLon&nbsp;getMovingLatLon()</pre>
+<div class="block">Returns a LatLon object containing the current coordinates of the object.
+ When you are dragging the image this changes.</div>
+<dl>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>The LatLon object with the position of the object.</dd>
+</dl>
+</li>
+</ul>
+<a name="getSequence--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>getSequence</h4>
+<pre>public&nbsp;org.openstreetmap.josm.plugins.streetside.StreetsideSequence&nbsp;getSequence()</pre>
+<div class="block">Returns the sequence which contains this image. Never null.</div>
+<dl>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>The StreetsideSequence object that contains this StreetsideImage.</dd>
+</dl>
+</li>
+</ul>
+<a name="getTempHe--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>getTempHe</h4>
+<pre>public&nbsp;double&nbsp;getTempHe()</pre>
+<div class="block">Returns the last fixed direction of the object.</div>
+<dl>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>The last fixed direction of the object. 0 means north.</dd>
+</dl>
+</li>
+</ul>
+<a name="getTempLatLon--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>getTempLatLon</h4>
+<pre>public&nbsp;org.openstreetmap.josm.data.coor.LatLon&nbsp;getTempLatLon()</pre>
+<div class="block">Returns the last fixed coordinates of the object.</div>
+<dl>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>A LatLon object containing.</dd>
+</dl>
+</li>
+</ul>
+<a name="isModified--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>isModified</h4>
+<pre>public&nbsp;boolean&nbsp;isModified()</pre>
+<div class="block">Returns whether the object has been modified or not.</div>
+<dl>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>true if the object has been modified; false otherwise.</dd>
+</dl>
+</li>
+</ul>
+<a name="isVisible--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>isVisible</h4>
+<pre>public&nbsp;boolean&nbsp;isVisible()</pre>
+<div class="block">Returns whether the image is visible on the map or not.</div>
+<dl>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>True if the image is visible; false otherwise.</dd>
+</dl>
+</li>
+</ul>
+<a name="move-double-double-">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>move</h4>
+<pre>public&nbsp;void&nbsp;move(double&nbsp;x,
+                 double&nbsp;y)</pre>
+<div class="block">Moves the image temporally to another position</div>
+<dl>
+<dt><span class="paramLabel">Parameters:</span></dt>
+<dd><code>x</code> - The movement of the image in longitude units.</dd>
+<dd><code>y</code> - The movement of the image in latitude units.</dd>
+</dl>
+</li>
+</ul>
+<a name="next--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>next</h4>
+<pre>public&nbsp;<a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a>&nbsp;next()</pre>
+<div class="block">If the StreetsideImage belongs to a StreetsideSequence, returns the next
+ image in the sequence.</div>
+<dl>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>The following StreetsideImage, or null if there is none.</dd>
+</dl>
+</li>
+</ul>
+<a name="previous--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>previous</h4>
+<pre>public&nbsp;<a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a>&nbsp;previous()</pre>
+<div class="block">If the StreetsideImage belongs to a StreetsideSequence, returns the previous
+ image in the sequence.</div>
+<dl>
+<dt><span class="returnLabel">Returns:</span></dt>
+<dd>The previous StreetsideImage, or null if there is none.</dd>
+</dl>
+</li>
+</ul>
+<a name="setHe-double-">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>setHe</h4>
+<pre>public&nbsp;void&nbsp;setHe(double&nbsp;he)</pre>
+</li>
+</ul>
+<a name="setCd-long-">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>setCd</h4>
+<pre>public&nbsp;void&nbsp;setCd(long&nbsp;cd)</pre>
+<div class="block">Sets the Epoch time when the picture was captured.</div>
+<dl>
+<dt><span class="paramLabel">Parameters:</span></dt>
+<dd><code>cd</code> - Epoch time when the image was captured.</dd>
+</dl>
+</li>
+</ul>
+<a name="setLatLon-org.openstreetmap.josm.data.coor.LatLon-">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>setLatLon</h4>
+<pre>public&nbsp;void&nbsp;setLatLon(org.openstreetmap.josm.data.coor.LatLon&nbsp;latLon)</pre>
+</li>
+</ul>
+<a name="setSequence-org.openstreetmap.josm.plugins.streetside.StreetsideSequence-">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>setSequence</h4>
+<pre>public&nbsp;void&nbsp;setSequence(org.openstreetmap.josm.plugins.streetside.StreetsideSequence&nbsp;sequence)</pre>
+<div class="block">Sets the StreetsideSequence object which contains the StreetsideImage.</div>
+<dl>
+<dt><span class="paramLabel">Parameters:</span></dt>
+<dd><code>sequence</code> - The StreetsideSequence that contains the StreetsideImage.</dd>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code>java.lang.IllegalArgumentException</code> - if the image is not already part of the
+             <code>StreetsideSequence</code>. Call
+             <code>StreetsideSequence.add(StreetsideAbstractImage)</code> first.</dd>
+</dl>
+</li>
+</ul>
+<a name="setVisible-boolean-">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>setVisible</h4>
+<pre>public&nbsp;void&nbsp;setVisible(boolean&nbsp;visible)</pre>
+<div class="block">Set's whether the image should be visible on the map or not.</div>
+<dl>
+<dt><span class="paramLabel">Parameters:</span></dt>
+<dd><code>visible</code> - true if the image is set to be visible; false otherwise.</dd>
+</dl>
+</li>
+</ul>
+<a name="stopMoving--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>stopMoving</h4>
+<pre>public&nbsp;void&nbsp;stopMoving()</pre>
+<div class="block">Called when the mouse button is released, meaning that the picture has
+ stopped being dragged, so the temporal values are saved.</div>
+</li>
+</ul>
+<a name="turn-double-">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>turn</h4>
+<pre>public&nbsp;void&nbsp;turn(double&nbsp;ca)</pre>
+<div class="block">Turns the image direction.</div>
+<dl>
+<dt><span class="paramLabel">Parameters:</span></dt>
+<dd><code>ca</code> - The angle the image is moving.</dd>
+</dl>
+</li>
+</ul>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<!-- ========= END OF CLASS DATA ========= -->
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li class="navBarCell1Rev">Class</li>
+<li><a href="class-use/StreetsideAbstractImage.html">Use</a></li>
+<li><a href="package-tree.html">Tree</a></li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-files/index-1.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev&nbsp;Class</li>
+<li>Next&nbsp;Class</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" target="_top">Frames</a></li>
+<li><a href="StreetsideAbstractImage.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<div>
+<ul class="subNavList">
+<li>Summary:&nbsp;</li>
+<li>Nested&nbsp;|&nbsp;</li>
+<li>Field&nbsp;|&nbsp;</li>
+<li>Constr&nbsp;|&nbsp;</li>
+<li><a href="#method.summary">Method</a></li>
+</ul>
+<ul class="subNavList">
+<li>Detail:&nbsp;</li>
+<li>Field&nbsp;|&nbsp;</li>
+<li>Constr&nbsp;|&nbsp;</li>
+<li><a href="#method.detail">Method</a></li>
+</ul>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/class-use/StreetsideAbstractImage.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/class-use/StreetsideAbstractImage.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/class-use/StreetsideAbstractImage.html	(revision 34317)
@@ -0,0 +1,157 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>Uses of Class org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
+<script type="text/javascript" src="../../../../../../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="Uses of Class org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li><a href="../../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">Class</a></li>
+<li class="navBarCell1Rev">Use</li>
+<li><a href="../../../../../../overview-tree.html">Tree</a></li>
+<li><a href="../../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../../index-files/index-1.html">Index</a></li>
+<li><a href="../../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../../index.html?org/openstreetmap/josm/plugins/streetside/class-use/StreetsideAbstractImage.html" target="_top">Frames</a></li>
+<li><a href="StreetsideAbstractImage.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="header">
+<h2 title="Uses of Class org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage" class="title">Uses of Class<br>org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage</h2>
+</div>
+<div class="classUseContainer">
+<ul class="blockList">
+<li class="blockList">
+<ul class="blockList">
+<li class="blockList"><a name="org.openstreetmap.josm.plugins.streetside">
+<!--   -->
+</a>
+<h3>Uses of <a href="../../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a> in <a href="../../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html">org.openstreetmap.josm.plugins.streetside</a></h3>
+<table class="useSummary" border="0" cellpadding="3" cellspacing="0" summary="Use table, listing methods, and an explanation">
+<caption><span>Methods in <a href="../../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html">org.openstreetmap.josm.plugins.streetside</a> that return <a href="../../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></span><span class="tabEnd">&nbsp;</span></caption>
+<tr>
+<th class="colFirst" scope="col">Modifier and Type</th>
+<th class="colLast" scope="col">Method and Description</th>
+</tr>
+<tbody>
+<tr class="altColor">
+<td class="colFirst"><code><a href="../../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></code></td>
+<td class="colLast"><span class="typeNameLabel">StreetsideAbstractImage.</span><code><span class="memberNameLink"><a href="../../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#next--">next</a></span>()</code>
+<div class="block">If the StreetsideImage belongs to a StreetsideSequence, returns the next
+ image in the sequence.</div>
+</td>
+</tr>
+<tr class="rowColor">
+<td class="colFirst"><code><a href="../../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></code></td>
+<td class="colLast"><span class="typeNameLabel">StreetsideAbstractImage.</span><code><span class="memberNameLink"><a href="../../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html#previous--">previous</a></span>()</code>
+<div class="block">If the StreetsideImage belongs to a StreetsideSequence, returns the previous
+ image in the sequence.</div>
+</td>
+</tr>
+</tbody>
+</table>
+</li>
+</ul>
+</li>
+</ul>
+</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li><a href="../../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">Class</a></li>
+<li class="navBarCell1Rev">Use</li>
+<li><a href="../../../../../../overview-tree.html">Tree</a></li>
+<li><a href="../../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../../index-files/index-1.html">Index</a></li>
+<li><a href="../../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../../index.html?org/openstreetmap/josm/plugins/streetside/class-use/StreetsideAbstractImage.html" target="_top">Frames</a></li>
+<li><a href="StreetsideAbstractImage.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/package-frame.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/package-frame.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/package-frame.html	(revision 34317)
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>org.openstreetmap.josm.plugins.streetside</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
+<script type="text/javascript" src="../../../../../script.js"></script>
+</head>
+<body>
+<h1 class="bar"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html" target="classFrame">org.openstreetmap.josm.plugins.streetside</a></h1>
+<div class="indexContainer">
+<h2 title="Classes">Classes</h2>
+<ul title="Classes">
+<li><a href="StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside" target="classFrame">StreetsideAbstractImage</a></li>
+</ul>
+</div>
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/package-summary.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/package-summary.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/package-summary.html	(revision 34317)
@@ -0,0 +1,151 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>org.openstreetmap.josm.plugins.streetside</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
+<script type="text/javascript" src="../../../../../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="org.openstreetmap.josm.plugins.streetside";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li><a href="package-use.html">Use</a></li>
+<li><a href="package-tree.html">Tree</a></li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-files/index-1.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev&nbsp;Package</li>
+<li>Next&nbsp;Package</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/openstreetmap/josm/plugins/streetside/package-summary.html" target="_top">Frames</a></li>
+<li><a href="package-summary.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="header">
+<h1 title="Package" class="title">Package&nbsp;org.openstreetmap.josm.plugins.streetside</h1>
+<div class="docSummary">
+<div class="block">The main package in which all core-code (so at the moment all code) resides.</div>
+</div>
+<p>See:&nbsp;<a href="#package.description">Description</a></p>
+</div>
+<div class="contentContainer">
+<ul class="blockList">
+<li class="blockList">
+<table class="typeSummary" border="0" cellpadding="3" cellspacing="0" summary="Class Summary table, listing classes, and an explanation">
+<caption><span>Class Summary</span><span class="tabEnd">&nbsp;</span></caption>
+<tr>
+<th class="colFirst" scope="col">Class</th>
+<th class="colLast" scope="col">Description</th>
+</tr>
+<tbody>
+<tr class="altColor">
+<td class="colFirst"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a></td>
+<td class="colLast">
+<div class="block">Abstract superclass for all image objects.</div>
+</td>
+</tr>
+</tbody>
+</table>
+</li>
+</ul>
+<a name="package.description">
+<!--   -->
+</a>
+<h2 title="Package org.openstreetmap.josm.plugins.streetside Description">Package org.openstreetmap.josm.plugins.streetside Description</h2>
+<div class="block">The main package in which all core-code (so at the moment all code) resides.</div>
+</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li><a href="package-use.html">Use</a></li>
+<li><a href="package-tree.html">Tree</a></li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-files/index-1.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev&nbsp;Package</li>
+<li>Next&nbsp;Package</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/openstreetmap/josm/plugins/streetside/package-summary.html" target="_top">Frames</a></li>
+<li><a href="package-summary.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/package-tree.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/package-tree.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/package-tree.html	(revision 34317)
@@ -0,0 +1,131 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>org.openstreetmap.josm.plugins.streetside Class Hierarchy</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
+<script type="text/javascript" src="../../../../../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="org.openstreetmap.josm.plugins.streetside Class Hierarchy";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li class="navBarCell1Rev">Tree</li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-files/index-1.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/openstreetmap/josm/plugins/streetside/package-tree.html" target="_top">Frames</a></li>
+<li><a href="package-tree.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="header">
+<h1 class="title">Hierarchy For Package org.openstreetmap.josm.plugins.streetside</h1>
+</div>
+<div class="contentContainer">
+<h2 title="Class Hierarchy">Class Hierarchy</h2>
+<ul>
+<li type="circle">java.lang.Object
+<ul>
+<li type="circle">org.openstreetmap.josm.plugins.streetside.<a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside"><span class="typeNameLink">StreetsideAbstractImage</span></a> (implements java.lang.Comparable&lt;T&gt;)</li>
+</ul>
+</li>
+</ul>
+</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li class="navBarCell1Rev">Tree</li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-files/index-1.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/openstreetmap/josm/plugins/streetside/package-tree.html" target="_top">Frames</a></li>
+<li><a href="package-tree.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/package-use.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/package-use.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/org/openstreetmap/josm/plugins/streetside/package-use.html	(revision 34317)
@@ -0,0 +1,147 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>Uses of Package org.openstreetmap.josm.plugins.streetside</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="../../../../../stylesheet.css" title="Style">
+<script type="text/javascript" src="../../../../../script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="Uses of Package org.openstreetmap.josm.plugins.streetside";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li class="navBarCell1Rev">Use</li>
+<li><a href="package-tree.html">Tree</a></li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-files/index-1.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/openstreetmap/josm/plugins/streetside/package-use.html" target="_top">Frames</a></li>
+<li><a href="package-use.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="header">
+<h1 title="Uses of Package org.openstreetmap.josm.plugins.streetside" class="title">Uses of Package<br>org.openstreetmap.josm.plugins.streetside</h1>
+</div>
+<div class="contentContainer">
+<ul class="blockList">
+<li class="blockList"><a name="org.openstreetmap.josm.plugins.streetside">
+<!--   -->
+</a>
+<table class="useSummary" border="0" cellpadding="3" cellspacing="0" summary="Use table, listing classes, and an explanation">
+<caption><span>Classes in <a href="../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html">org.openstreetmap.josm.plugins.streetside</a> used by <a href="../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html">org.openstreetmap.josm.plugins.streetside</a></span><span class="tabEnd">&nbsp;</span></caption>
+<tr>
+<th class="colOne" scope="col">Class and Description</th>
+</tr>
+<tbody>
+<tr class="altColor">
+<td class="colOne"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/class-use/StreetsideAbstractImage.html#org.openstreetmap.josm.plugins.streetside">StreetsideAbstractImage</a>
+<div class="block">Abstract superclass for all image objects.</div>
+</td>
+</tr>
+<tr class="rowColor">
+<td class="colOne"><a href="../../../../../org/openstreetmap/josm/plugins/streetside/class-use/StreetsideSequence.html#org.openstreetmap.josm.plugins.streetside">StreetsideSequence</a>
+<div class="block">Class that stores a sequence of <a href="../../../../../org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside"><code>StreetsideAbstractImage</code></a> objects.</div>
+</td>
+</tr>
+</tbody>
+</table>
+</li>
+</ul>
+</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="../../../../../org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li class="navBarCell1Rev">Use</li>
+<li><a href="package-tree.html">Tree</a></li>
+<li><a href="../../../../../deprecated-list.html">Deprecated</a></li>
+<li><a href="../../../../../index-files/index-1.html">Index</a></li>
+<li><a href="../../../../../help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="../../../../../index.html?org/openstreetmap/josm/plugins/streetside/package-use.html" target="_top">Frames</a></li>
+<li><a href="package-use.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="../../../../../allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/overview-tree.html
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/overview-tree.html	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/overview-tree.html	(revision 34317)
@@ -0,0 +1,135 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!-- NewPage -->
+<html lang="en">
+<head>
+<!-- Generated by javadoc (1.8.0_171) on Fri Jun 15 14:15:27 PDT 2018 -->
+<title>Class Hierarchy</title>
+<meta name="date" content="2018-06-15">
+<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
+<script type="text/javascript" src="script.js"></script>
+</head>
+<body>
+<script type="text/javascript"><!--
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="Class Hierarchy";
+        }
+    }
+    catch(err) {
+    }
+//-->
+</script>
+<noscript>
+<div>JavaScript is disabled on your browser.</div>
+</noscript>
+<!-- ========= START OF TOP NAVBAR ======= -->
+<div class="topNav"><a name="navbar.top">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.top" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.top.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li class="navBarCell1Rev">Tree</li>
+<li><a href="deprecated-list.html">Deprecated</a></li>
+<li><a href="index-files/index-1.html">Index</a></li>
+<li><a href="help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="index.html?overview-tree.html" target="_top">Frames</a></li>
+<li><a href="overview-tree.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_top">
+<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_top");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.top">
+<!--   -->
+</a></div>
+<!-- ========= END OF TOP NAVBAR ========= -->
+<div class="header">
+<h1 class="title">Hierarchy For All Packages</h1>
+<span class="packageHierarchyLabel">Package Hierarchies:</span>
+<ul class="horizontal">
+<li><a href="org/openstreetmap/josm/plugins/streetside/package-tree.html">org.openstreetmap.josm.plugins.streetside</a></li>
+</ul>
+</div>
+<div class="contentContainer">
+<h2 title="Class Hierarchy">Class Hierarchy</h2>
+<ul>
+<li type="circle">java.lang.Object
+<ul>
+<li type="circle">org.openstreetmap.josm.plugins.streetside.<a href="org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.html" title="class in org.openstreetmap.josm.plugins.streetside"><span class="typeNameLink">StreetsideAbstractImage</span></a> (implements java.lang.Comparable&lt;T&gt;)</li>
+</ul>
+</li>
+</ul>
+</div>
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<div class="bottomNav"><a name="navbar.bottom">
+<!--   -->
+</a>
+<div class="skipNav"><a href="#skip.navbar.bottom" title="Skip navigation links">Skip navigation links</a></div>
+<a name="navbar.bottom.firstrow">
+<!--   -->
+</a>
+<ul class="navList" title="Navigation">
+<li><a href="org/openstreetmap/josm/plugins/streetside/package-summary.html">Package</a></li>
+<li>Class</li>
+<li>Use</li>
+<li class="navBarCell1Rev">Tree</li>
+<li><a href="deprecated-list.html">Deprecated</a></li>
+<li><a href="index-files/index-1.html">Index</a></li>
+<li><a href="help-doc.html">Help</a></li>
+</ul>
+</div>
+<div class="subNav">
+<ul class="navList">
+<li>Prev</li>
+<li>Next</li>
+</ul>
+<ul class="navList">
+<li><a href="index.html?overview-tree.html" target="_top">Frames</a></li>
+<li><a href="overview-tree.html" target="_top">No&nbsp;Frames</a></li>
+</ul>
+<ul class="navList" id="allclasses_navbar_bottom">
+<li><a href="allclasses-noframe.html">All&nbsp;Classes</a></li>
+</ul>
+<div>
+<script type="text/javascript"><!--
+  allClassesLink = document.getElementById("allclasses_navbar_bottom");
+  if(window==top) {
+    allClassesLink.style.display = "block";
+  }
+  else {
+    allClassesLink.style.display = "none";
+  }
+  //-->
+</script>
+</div>
+<a name="skip.navbar.bottom">
+<!--   -->
+</a></div>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+</body>
+</html>
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/package-list
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/package-list	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/package-list	(revision 34317)
@@ -0,0 +1,1 @@
+org.openstreetmap.josm.plugins.streetside
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/script.js
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/script.js	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/script.js	(revision 34317)
@@ -0,0 +1,30 @@
+function show(type)
+{
+    count = 0;
+    for (var key in methods) {
+        var row = document.getElementById(key);
+        if ((methods[key] &  type) != 0) {
+            row.style.display = '';
+            row.className = (count++ % 2) ? rowColor : altColor;
+        }
+        else
+            row.style.display = 'none';
+    }
+    updateTabs(type);
+}
+
+function updateTabs(type)
+{
+    for (var value in tabs) {
+        var sNode = document.getElementById(tabs[value][0]);
+        var spanNode = sNode.firstChild;
+        if (value == type) {
+            sNode.className = activeTableTab;
+            spanNode.innerHTML = tabs[value][1];
+        }
+        else {
+            sNode.className = tableTab;
+            spanNode.innerHTML = "<a href=\"javascript:show("+ value + ");\">" + tabs[value][1] + "</a>";
+        }
+    }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/doc/stylesheet.css
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/doc/stylesheet.css	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/doc/stylesheet.css	(revision 34317)
@@ -0,0 +1,574 @@
+/* Javadoc style sheet */
+/*
+Overall document style
+*/
+
+@import url('resources/fonts/dejavu.css');
+
+body {
+    background-color:#ffffff;
+    color:#353833;
+    font-family:'DejaVu Sans', Arial, Helvetica, sans-serif;
+    font-size:14px;
+    margin:0;
+}
+a:link, a:visited {
+    text-decoration:none;
+    color:#4A6782;
+}
+a:hover, a:focus {
+    text-decoration:none;
+    color:#bb7a2a;
+}
+a:active {
+    text-decoration:none;
+    color:#4A6782;
+}
+a[name] {
+    color:#353833;
+}
+a[name]:hover {
+    text-decoration:none;
+    color:#353833;
+}
+pre {
+    font-family:'DejaVu Sans Mono', monospace;
+    font-size:14px;
+}
+h1 {
+    font-size:20px;
+}
+h2 {
+    font-size:18px;
+}
+h3 {
+    font-size:16px;
+    font-style:italic;
+}
+h4 {
+    font-size:13px;
+}
+h5 {
+    font-size:12px;
+}
+h6 {
+    font-size:11px;
+}
+ul {
+    list-style-type:disc;
+}
+code, tt {
+    font-family:'DejaVu Sans Mono', monospace;
+    font-size:14px;
+    padding-top:4px;
+    margin-top:8px;
+    line-height:1.4em;
+}
+dt code {
+    font-family:'DejaVu Sans Mono', monospace;
+    font-size:14px;
+    padding-top:4px;
+}
+table tr td dt code {
+    font-family:'DejaVu Sans Mono', monospace;
+    font-size:14px;
+    vertical-align:top;
+    padding-top:4px;
+}
+sup {
+    font-size:8px;
+}
+/*
+Document title and Copyright styles
+*/
+.clear {
+    clear:both;
+    height:0px;
+    overflow:hidden;
+}
+.aboutLanguage {
+    float:right;
+    padding:0px 21px;
+    font-size:11px;
+    z-index:200;
+    margin-top:-9px;
+}
+.legalCopy {
+    margin-left:.5em;
+}
+.bar a, .bar a:link, .bar a:visited, .bar a:active {
+    color:#FFFFFF;
+    text-decoration:none;
+}
+.bar a:hover, .bar a:focus {
+    color:#bb7a2a;
+}
+.tab {
+    background-color:#0066FF;
+    color:#ffffff;
+    padding:8px;
+    width:5em;
+    font-weight:bold;
+}
+/*
+Navigation bar styles
+*/
+.bar {
+    background-color:#4D7A97;
+    color:#FFFFFF;
+    padding:.8em .5em .4em .8em;
+    height:auto;/*height:1.8em;*/
+    font-size:11px;
+    margin:0;
+}
+.topNav {
+    background-color:#4D7A97;
+    color:#FFFFFF;
+    float:left;
+    padding:0;
+    width:100%;
+    clear:right;
+    height:2.8em;
+    padding-top:10px;
+    overflow:hidden;
+    font-size:12px; 
+}
+.bottomNav {
+    margin-top:10px;
+    background-color:#4D7A97;
+    color:#FFFFFF;
+    float:left;
+    padding:0;
+    width:100%;
+    clear:right;
+    height:2.8em;
+    padding-top:10px;
+    overflow:hidden;
+    font-size:12px;
+}
+.subNav {
+    background-color:#dee3e9;
+    float:left;
+    width:100%;
+    overflow:hidden;
+    font-size:12px;
+}
+.subNav div {
+    clear:left;
+    float:left;
+    padding:0 0 5px 6px;
+    text-transform:uppercase;
+}
+ul.navList, ul.subNavList {
+    float:left;
+    margin:0 25px 0 0;
+    padding:0;
+}
+ul.navList li{
+    list-style:none;
+    float:left;
+    padding: 5px 6px;
+    text-transform:uppercase;
+}
+ul.subNavList li{
+    list-style:none;
+    float:left;
+}
+.topNav a:link, .topNav a:active, .topNav a:visited, .bottomNav a:link, .bottomNav a:active, .bottomNav a:visited {
+    color:#FFFFFF;
+    text-decoration:none;
+    text-transform:uppercase;
+}
+.topNav a:hover, .bottomNav a:hover {
+    text-decoration:none;
+    color:#bb7a2a;
+    text-transform:uppercase;
+}
+.navBarCell1Rev {
+    background-color:#F8981D;
+    color:#253441;
+    margin: auto 5px;
+}
+.skipNav {
+    position:absolute;
+    top:auto;
+    left:-9999px;
+    overflow:hidden;
+}
+/*
+Page header and footer styles
+*/
+.header, .footer {
+    clear:both;
+    margin:0 20px;
+    padding:5px 0 0 0;
+}
+.indexHeader {
+    margin:10px;
+    position:relative;
+}
+.indexHeader span{
+    margin-right:15px;
+}
+.indexHeader h1 {
+    font-size:13px;
+}
+.title {
+    color:#2c4557;
+    margin:10px 0;
+}
+.subTitle {
+    margin:5px 0 0 0;
+}
+.header ul {
+    margin:0 0 15px 0;
+    padding:0;
+}
+.footer ul {
+    margin:20px 0 5px 0;
+}
+.header ul li, .footer ul li {
+    list-style:none;
+    font-size:13px;
+}
+/*
+Heading styles
+*/
+div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 {
+    background-color:#dee3e9;
+    border:1px solid #d0d9e0;
+    margin:0 0 6px -8px;
+    padding:7px 5px;
+}
+ul.blockList ul.blockList ul.blockList li.blockList h3 {
+    background-color:#dee3e9;
+    border:1px solid #d0d9e0;
+    margin:0 0 6px -8px;
+    padding:7px 5px;
+}
+ul.blockList ul.blockList li.blockList h3 {
+    padding:0;
+    margin:15px 0;
+}
+ul.blockList li.blockList h2 {
+    padding:0px 0 20px 0;
+}
+/*
+Page layout container styles
+*/
+.contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer {
+    clear:both;
+    padding:10px 20px;
+    position:relative;
+}
+.indexContainer {
+    margin:10px;
+    position:relative;
+    font-size:12px;
+}
+.indexContainer h2 {
+    font-size:13px;
+    padding:0 0 3px 0;
+}
+.indexContainer ul {
+    margin:0;
+    padding:0;
+}
+.indexContainer ul li {
+    list-style:none;
+    padding-top:2px;
+}
+.contentContainer .description dl dt, .contentContainer .details dl dt, .serializedFormContainer dl dt {
+    font-size:12px;
+    font-weight:bold;
+    margin:10px 0 0 0;
+    color:#4E4E4E;
+}
+.contentContainer .description dl dd, .contentContainer .details dl dd, .serializedFormContainer dl dd {
+    margin:5px 0 10px 0px;
+    font-size:14px;
+    font-family:'DejaVu Sans Mono',monospace;
+}
+.serializedFormContainer dl.nameValue dt {
+    margin-left:1px;
+    font-size:1.1em;
+    display:inline;
+    font-weight:bold;
+}
+.serializedFormContainer dl.nameValue dd {
+    margin:0 0 0 1px;
+    font-size:1.1em;
+    display:inline;
+}
+/*
+List styles
+*/
+ul.horizontal li {
+    display:inline;
+    font-size:0.9em;
+}
+ul.inheritance {
+    margin:0;
+    padding:0;
+}
+ul.inheritance li {
+    display:inline;
+    list-style:none;
+}
+ul.inheritance li ul.inheritance {
+    margin-left:15px;
+    padding-left:15px;
+    padding-top:1px;
+}
+ul.blockList, ul.blockListLast {
+    margin:10px 0 10px 0;
+    padding:0;
+}
+ul.blockList li.blockList, ul.blockListLast li.blockList {
+    list-style:none;
+    margin-bottom:15px;
+    line-height:1.4;
+}
+ul.blockList ul.blockList li.blockList, ul.blockList ul.blockListLast li.blockList {
+    padding:0px 20px 5px 10px;
+    border:1px solid #ededed; 
+    background-color:#f8f8f8;
+}
+ul.blockList ul.blockList ul.blockList li.blockList, ul.blockList ul.blockList ul.blockListLast li.blockList {
+    padding:0 0 5px 8px;
+    background-color:#ffffff;
+    border:none;
+}
+ul.blockList ul.blockList ul.blockList ul.blockList li.blockList {
+    margin-left:0;
+    padding-left:0;
+    padding-bottom:15px;
+    border:none;
+}
+ul.blockList ul.blockList ul.blockList ul.blockList li.blockListLast {
+    list-style:none;
+    border-bottom:none;
+    padding-bottom:0;
+}
+table tr td dl, table tr td dl dt, table tr td dl dd {
+    margin-top:0;
+    margin-bottom:1px;
+}
+/*
+Table styles
+*/
+.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary {
+    width:100%;
+    border-left:1px solid #EEE; 
+    border-right:1px solid #EEE; 
+    border-bottom:1px solid #EEE; 
+}
+.overviewSummary, .memberSummary  {
+    padding:0px;
+}
+.overviewSummary caption, .memberSummary caption, .typeSummary caption,
+.useSummary caption, .constantsSummary caption, .deprecatedSummary caption {
+    position:relative;
+    text-align:left;
+    background-repeat:no-repeat;
+    color:#253441;
+    font-weight:bold;
+    clear:none;
+    overflow:hidden;
+    padding:0px;
+    padding-top:10px;
+    padding-left:1px;
+    margin:0px;
+    white-space:pre;
+}
+.overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link,
+.useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link,
+.overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover,
+.useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover,
+.overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active,
+.useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active,
+.overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited,
+.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited {
+    color:#FFFFFF;
+}
+.overviewSummary caption span, .memberSummary caption span, .typeSummary caption span,
+.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span {
+    white-space:nowrap;
+    padding-top:5px;
+    padding-left:12px;
+    padding-right:12px;
+    padding-bottom:7px;
+    display:inline-block;
+    float:left;
+    background-color:#F8981D;
+    border: none;
+    height:16px;
+}
+.memberSummary caption span.activeTableTab span {
+    white-space:nowrap;
+    padding-top:5px;
+    padding-left:12px;
+    padding-right:12px;
+    margin-right:3px;
+    display:inline-block;
+    float:left;
+    background-color:#F8981D;
+    height:16px;
+}
+.memberSummary caption span.tableTab span {
+    white-space:nowrap;
+    padding-top:5px;
+    padding-left:12px;
+    padding-right:12px;
+    margin-right:3px;
+    display:inline-block;
+    float:left;
+    background-color:#4D7A97;
+    height:16px;
+}
+.memberSummary caption span.tableTab, .memberSummary caption span.activeTableTab {
+    padding-top:0px;
+    padding-left:0px;
+    padding-right:0px;
+    background-image:none;
+    float:none;
+    display:inline;
+}
+.overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd,
+.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd {
+    display:none;
+    width:5px;
+    position:relative;
+    float:left;
+    background-color:#F8981D;
+}
+.memberSummary .activeTableTab .tabEnd {
+    display:none;
+    width:5px;
+    margin-right:3px;
+    position:relative; 
+    float:left;
+    background-color:#F8981D;
+}
+.memberSummary .tableTab .tabEnd {
+    display:none;
+    width:5px;
+    margin-right:3px;
+    position:relative;
+    background-color:#4D7A97;
+    float:left;
+
+}
+.overviewSummary td, .memberSummary td, .typeSummary td,
+.useSummary td, .constantsSummary td, .deprecatedSummary td {
+    text-align:left;
+    padding:0px 0px 12px 10px;
+}
+th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th,
+td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{
+    vertical-align:top;
+    padding-right:0px;
+    padding-top:8px;
+    padding-bottom:3px;
+}
+th.colFirst, th.colLast, th.colOne, .constantsSummary th {
+    background:#dee3e9;
+    text-align:left;
+    padding:8px 3px 3px 7px;
+}
+td.colFirst, th.colFirst {
+    white-space:nowrap;
+    font-size:13px;
+}
+td.colLast, th.colLast {
+    font-size:13px;
+}
+td.colOne, th.colOne {
+    font-size:13px;
+}
+.overviewSummary td.colFirst, .overviewSummary th.colFirst,
+.useSummary td.colFirst, .useSummary th.colFirst,
+.overviewSummary td.colOne, .overviewSummary th.colOne,
+.memberSummary td.colFirst, .memberSummary th.colFirst,
+.memberSummary td.colOne, .memberSummary th.colOne,
+.typeSummary td.colFirst{
+    width:25%;
+    vertical-align:top;
+}
+td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
+    font-weight:bold;
+}
+.tableSubHeadingColor {
+    background-color:#EEEEFF;
+}
+.altColor {
+    background-color:#FFFFFF;
+}
+.rowColor {
+    background-color:#EEEEEF;
+}
+/*
+Content styles
+*/
+.description pre {
+    margin-top:0;
+}
+.deprecatedContent {
+    margin:0;
+    padding:10px 0;
+}
+.docSummary {
+    padding:0;
+}
+
+ul.blockList ul.blockList ul.blockList li.blockList h3 {
+    font-style:normal;
+}
+
+div.block {
+    font-size:14px;
+    font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif;
+}
+
+td.colLast div {
+    padding-top:0px;
+}
+
+
+td.colLast a {
+    padding-bottom:3px;
+}
+/*
+Formatting effect styles
+*/
+.sourceLineNo {
+    color:green;
+    padding:0 30px 0 0;
+}
+h1.hidden {
+    visibility:hidden;
+    overflow:hidden;
+    font-size:10px;
+}
+.block {
+    display:block;
+    margin:3px 10px 2px 0px;
+    color:#474747;
+}
+.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink,
+.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel,
+.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink {
+    font-weight:bold;
+}
+.deprecationComment, .emphasizedPhrase, .interfaceName {
+    font-style:italic;
+}
+
+div.block div.block span.deprecationComment, div.block div.block span.emphasizedPhrase,
+div.block div.block span.interfaceName {
+    font-style:normal;
+}
+
+div.contentContainer ul.blockList li.blockList h2{
+    padding-bottom:0px;
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/gradle.properties
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/gradle.properties	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/gradle.properties	(revision 34317)
@@ -0,0 +1,18 @@
+plugin.author=renerr18
+plugin.canloadatruntime=true
+plugin.class=org.openstreetmap.josm.plugins.streetside.StreetsidePlugin
+plugin.description=Allows the user to work with pictures hosted at Microsoft Streetside
+plugin.icon=images/streetside-logo.svg
+plugin.link=https://wiki.openstreetmap.org/wiki/JOSM/Plugins/MicrosoftStreetside
+
+# Minimum required JOSM version to run this plugin, choose the lowest version possible that is compatible.
+# You can check if the plugin compiles against this version by executing `./gradlew minJosmVersionClasses`.
+plugin.main.version=13878
+# Version of JOSM against which the plugin is compiled
+# Please check, if the specified version is available for download from https://josm.openstreetmap.de/download/ .
+# If not, choose the next higher number that is available, or the gradle build will break.
+plugin.compile.version=13878
+plugin.requires=apache-commons;apache-http
+
+# Character encoding of Gradle files
+systemProp.file.encoding=utf-8
Index: applications/editors/josm/plugins/MicrosoftStreetside/gradle/markdown.gradle
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/gradle/markdown.gradle	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/gradle/markdown.gradle	(revision 34317)
@@ -0,0 +1,26 @@
+import groovy.io.FileType
+
+task prepareMarkdown(type:Sync) {
+  from projectDir
+  //into "$buildDir/src/markdown"
+  into "$buildDir"
+  include 'LICENSE.md'
+  include 'README.md'
+}
+
+markdownToHtml {
+  dependsOn prepareMarkdown
+  sourceDir new File("$buildDir/src/markdown")
+  inputEncoding 'UTF-8'
+  outputEncoding 'UTF-8'
+  fencedCodeBlocks true
+  autoLinks true
+
+  doLast {
+    new File("$outputDir").eachFileRecurse(FileType.FILES, { file ->
+      file.text = '<!DOCTYPE html><meta charset="utf-8">' + file.text
+    })
+  }
+}
+jar.dependsOn markdownToHtml
+jar.from markdownToHtml.outputDir
Index: applications/editors/josm/plugins/MicrosoftStreetside/gradle/tool-config.gradle
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/gradle/tool-config.gradle	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/gradle/tool-config.gradle	(revision 34317)
@@ -0,0 +1,60 @@
+def pmdVersion = "5.8.1"
+def spotbugsVersion = "3.1.1"
+def jacocoVersion = "0.7.9"
+def errorproneVersion = "2.2.0"
+
+// Set up ErrorProne (currently only for JDK8, until JDK9 is supported)
+dependencies.errorprone "com.google.errorprone:error_prone_core:$errorproneVersion"
+tasks.withType(JavaCompile) {
+options.compilerArgs += ['-Xep:DefaultCharset:ERROR',
+  '-Xep:ClassCanBeStatic:ERROR',
+  '-Xep:StringEquality:ERROR',
+  '-Xep:MethodCanBeStatic:WARN',
+  '-Xep:RemoveUnusedImports:WARN',
+  '-Xep:PrivateConstructorForUtilityClass:WARN',
+  '-Xep:WildcardImport:WARN',
+  '-Xep:LambdaFunctionalInterface:WARN',
+  '-Xep:ConstantField:WARN']
+}
+
+// Spotbugs config
+spotbugs {
+  toolVersion = spotbugsVersion
+  ignoreFailures = true
+  effort = "max"
+  reportLevel = "low"
+  sourceSets = [sourceSets.main, sourceSets.test]
+}
+
+// JaCoCo config
+jacoco {
+  toolVersion = jacocoVersion
+}
+jacocoTestReport {
+  reports {
+    xml.enabled = true
+    html.destination file("$buildDir/reports/jacoco")
+  }
+}
+build.dependsOn jacocoTestReport
+
+// PMD config
+pmd {
+  toolVersion pmdVersion
+  ignoreFailures true
+  ruleSetConfig = resources.text.fromFile('config/pmd/ruleset.xml')
+  sourceSets = [sourceSets.main, sourceSets.test]
+}
+
+// SonarQube config
+sonarqube {
+  properties {
+    property 'sonar.forceAuthentication', 'true'
+    property 'sonar.host.url', 'https://sonarqube.com'
+    property 'sonar.projectKey', 'org.openstreetmap.josm.plugins:Microsoft-Streetside'
+    property 'sonar.projectName', 'ms-streetside-josm-plugin'
+    property 'sonar.projectVersion', project.version
+    property 'sonar.projectDescription', property('plugin.description')
+    property 'sonar.sources', ['src']
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/gradle/wrapper/gradle-wrapper.properties
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/gradle/wrapper/gradle-wrapper.properties	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/gradle/wrapper/gradle-wrapper.properties	(revision 34317)
@@ -0,0 +1,6 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.3-all.zip
+distributionSha256Sum=b3afcc2d5aaf4d23eeab2409d64c54046147322d05acc7fb5a63f84d8a2b8bd7
Index: applications/editors/josm/plugins/MicrosoftStreetside/gradlew
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/gradlew	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/gradlew	(revision 34317)
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
Index: applications/editors/josm/plugins/MicrosoftStreetside/gradlew.bat
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/gradlew.bat	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/gradlew.bat	(revision 34317)
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/blue.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/blue.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/blue.svg	(revision 34317)
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   version="1.0"
+   width="128"
+   height="128">
+  <defs>
+    <linearGradient
+       id="linearGradient2816">
+      <stop
+         style="stop-color:#0000a2;stop-opacity:1"
+         offset="0" />
+      <stop
+         style="stop-color:#fff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2794">
+      <stop
+         style="stop-color:#545454;stop-opacity:1"
+         offset="0" />
+      <stop
+         style="stop-color:#545454;stop-opacity:1"
+         offset="0.9464286" />
+      <stop
+         style="stop-color:#c5c5c5;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2760">
+      <stop
+         style="stop-color:#00f;stop-opacity:1"
+         offset="0" />
+      <stop
+         style="stop-color:#0000a2;stop-opacity:1"
+         offset="0.61160713" />
+      <stop
+         style="stop-color:#66f;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       x1="6.9292336"
+       y1="121.07077"
+       x2="6.9292336"
+       y2="8.9609833"
+       id="linearGradient2766"
+       xlink:href="#linearGradient2760"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       cx="62.984127"
+       cy="65.015877"
+       r="54.179893"
+       fx="62.984127"
+       fy="65.015877"
+       id="radialGradient2812"
+       xlink:href="#linearGradient2794"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       x1="31.5"
+       y1="63"
+       x2="31.5"
+       y2="12"
+       id="linearGradient2822"
+       xlink:href="#linearGradient2816"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <path
+     d="M 117.16402,65.015877 C 117.16402,94.938606 92.906856,119.19577 62.984127,119.19577 C 33.061398,119.19577 8.8042336,94.938606 8.8042336,65.015877 C 8.8042336,35.093148 33.061398,10.835984 62.984127,10.835984 C 92.906856,10.835984 117.16402,35.093148 117.16402,65.015877 z "
+     transform="translate(5.724864,4.031744)"
+     style="opacity:1;fill:url(#radialGradient2812);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/>
+  <path
+     d="M 117.16402,65.015877 C 117.16402,94.938606 92.906856,119.19577 62.984127,119.19577 C 33.061398,119.19577 8.8042336,94.938606 8.8042336,65.015877 C 8.8042336,35.093148 33.061398,10.835984 62.984127,10.835984 C 92.906856,10.835984 117.16402,35.093148 117.16402,65.015877 z "
+     transform="translate(1.69312,0)"
+     style="opacity:1;fill:url(#linearGradient2766);fill-opacity:1;fill-rule:nonzero;stroke:#000074;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/>
+  <path
+     d="M 95.5,37.5 C 95.5,51.583261 81.173112,63 63.5,63 C 45.826888,63 31.5,51.583261 31.5,37.5 C 31.5,23.416739 45.826888,12 63.5,12 C 81.173112,12 95.5,23.416739 95.5,37.5 z "
+     transform="translate(1,2)"
+     style="opacity:1;fill:url(#linearGradient2822);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/>
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/red.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/red.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/red.svg	(revision 34317)
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   version="1.0"
+   width="128"
+   height="128">
+  <defs>
+    <linearGradient
+       id="linearGradient2816">
+      <stop
+         style="stop-color:#a20000;stop-opacity:1"
+         offset="0" />
+      <stop
+         style="stop-color:#fff;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2794">
+      <stop
+         style="stop-color:#545454;stop-opacity:1"
+         offset="0" />
+      <stop
+         style="stop-color:#545454;stop-opacity:1"
+         offset="0.9464286" />
+      <stop
+         style="stop-color:#c5c5c5;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2760">
+      <stop
+         style="stop-color:red;stop-opacity:1"
+         offset="0" />
+      <stop
+         style="stop-color:#a20000;stop-opacity:1"
+         offset="0.61160713" />
+      <stop
+         style="stop-color:#f66;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       x1="6.9292336"
+       y1="121.07077"
+       x2="6.9292336"
+       y2="8.9609833"
+       id="linearGradient2766"
+       xlink:href="#linearGradient2760"
+       gradientUnits="userSpaceOnUse" />
+    <radialGradient
+       cx="62.984127"
+       cy="65.015877"
+       r="54.179893"
+       fx="62.984127"
+       fy="65.015877"
+       id="radialGradient2812"
+       xlink:href="#linearGradient2794"
+       gradientUnits="userSpaceOnUse" />
+    <linearGradient
+       x1="31.5"
+       y1="63"
+       x2="31.5"
+       y2="12"
+       id="linearGradient2822"
+       xlink:href="#linearGradient2816"
+       gradientUnits="userSpaceOnUse" />
+  </defs>
+  <path
+     d="M 117.16402 65.015877 A 54.179893 54.179893 0 1 1  8.8042336,65.015877 A 54.179893 54.179893 0 1 1  117.16402 65.015877 z"
+     transform="translate(5.724864,4.031744)"
+     style="opacity:1;fill:url(#radialGradient2812);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/>
+  <path
+     d="M 117.16402 65.015877 A 54.179893 54.179893 0 1 1  8.8042336,65.015877 A 54.179893 54.179893 0 1 1  117.16402 65.015877 z"
+     transform="translate(1.69312,0)"
+     style="opacity:1;fill:url(#linearGradient2766);fill-opacity:1;fill-rule:nonzero;stroke:#740000;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/>
+  <path
+     d="M 95.5 37.5 A 32 25.5 0 1 1  31.5,37.5 A 32 25.5 0 1 1  95.5 37.5 z"
+     transform="translate(1,2)"
+     style="opacity:1;fill:url(#linearGradient2822);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.75;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"/>
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-filter.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-filter.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-filter.svg	(revision 34317)
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   sodipodi:docname="streetside-filter.svg"
+   inkscape:version="0.91 r13725"
+   id="svg2"
+   version="1.1"
+   width="24px"
+   height="24px"
+   viewBox="0 0 24 24">
+  <metadata
+     id="metadata12">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs10" />
+  <sodipodi:namedview
+     inkscape:current-layer="svg2"
+     inkscape:window-maximized="1"
+     inkscape:window-y="1"
+     inkscape:window-x="0"
+     inkscape:cy="12"
+     inkscape:cx="36.401593"
+     inkscape:zoom="9.8333333"
+     showgrid="false"
+     id="namedview8"
+     inkscape:window-height="806"
+     inkscape:window-width="1440"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0"
+     guidetolerance="10"
+     gridtolerance="10"
+     objecttolerance="10"
+     borderopacity="1"
+     bordercolor="#666666"
+     pagecolor="#ffffff" />
+  <path
+     d="M0,0 h100 v100 h-100z"
+     fill="#35af6d"
+     id="path4"
+     style="fill:#a3e6f0;fill-opacity:1" />
+  <path
+     d="M 3,2L 20.9888,2L 21,2L 21,2.01122L 21,3.99999L 20.9207,3.99999L 14,10.9207L 14,22.909L 9.99999,18.909L 10,10.906L 3.09405,3.99999L 3,3.99999L 3,2 Z"
+     fill="#fff"
+     transform="translate(12,12) scale(.8) translate(-12,-12)"
+     id="path6" />
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-history.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-history.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-history.svg	(revision 34317)
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   viewBox="0 0 24 24"
+   height="24px"
+   width="24px"
+   version="1.1"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="streetside-history.svg">
+  <metadata
+     id="metadata12">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs10" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1440"
+     inkscape:window-height="806"
+     id="namedview8"
+     showgrid="false"
+     inkscape:zoom="9.8333333"
+     inkscape:cx="11.898305"
+     inkscape:cy="12"
+     inkscape:window-x="0"
+     inkscape:window-y="1"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2" />
+  <path
+     d="M0,0 h24 v24 h-24z"
+     fill="#35af6d"
+     id="path4"
+     style="fill:#a3e6f0;fill-opacity:1" />
+  <path
+     d="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89.07.14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7 7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13 21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54.72-1.21-3.5-2.08V8H12z"
+     fill="#fff"
+     transform="translate(12,12) scale(.8) translate(-12,-12)"
+     id="path6" />
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-info.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-info.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-info.svg	(revision 34317)
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   viewBox="0 0 24 24"
+   height="24px"
+   width="24px"
+   version="1.1"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="streetside-info.svg">
+  <metadata
+     id="metadata12">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs10" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="845"
+     inkscape:window-height="480"
+     id="namedview8"
+     showgrid="false"
+     inkscape:zoom="9.8333333"
+     inkscape:cx="12"
+     inkscape:cy="12"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2" />
+  <path
+     d="M0,0 h24 v24 h-24z"
+     fill="#35af6d"
+     id="path4"
+     style="fill:#a3e6f0;fill-opacity:1" />
+  <path
+     d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z"
+     fill="#fff"
+     transform="translate(12,12) scale(.8) translate(-12,-12)"
+     id="path6" />
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-main.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-main.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-main.svg	(revision 34317)
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   viewBox="0 0 24 24"
+   height="24px"
+   width="24px"
+   version="1.1"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="streetside-main.svg">
+  <metadata
+     id="metadata12">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs10" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="845"
+     inkscape:window-height="480"
+     id="namedview8"
+     showgrid="false"
+     inkscape:zoom="9.8333333"
+     inkscape:cx="12"
+     inkscape:cy="12"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg2" />
+  <path
+     d="M0,0 h24 v24 h-24z"
+     fill="#35af6d"
+     id="path4"
+     style="fill:#a3e6f0;fill-opacity:1" />
+  <path
+     d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"
+     fill="#fff"
+     transform="translate(12,12) scale(.8) translate(-12,-12)"
+     id="path6" />
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-upload.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-upload.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-upload.svg	(revision 34317)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24px" width="24px" version="1.1">
+  <path d="M0,0 h24 v24 h-24z" fill="#35af6d"/>
+  <path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z" fill="#fff" transform="translate(12,12) scale(.8) translate(-12,-12)"/>
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-viewer.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-viewer.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/dialogs/streetside-viewer.svg	(revision 34317)
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   viewBox="0 0 24 24"
+   height="24px"
+   width="24px"
+   version="1.1"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="streetside-viewer.svg">
+  <metadata
+     id="metadata12">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs10" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1440"
+     inkscape:window-height="806"
+     id="namedview8"
+     showgrid="false"
+     inkscape:zoom="13.906433"
+     inkscape:cx="25.620771"
+     inkscape:cy="14.883623"
+     inkscape:window-x="0"
+     inkscape:window-y="1"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2" />
+  <path
+     d="M0,0 h24 v24 h-24z"
+     fill="#35af6d"
+     id="path4"
+     style="fill:#a3e6f0;fill-opacity:1" />
+  <text
+     xml:space="preserve"
+     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.5px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     x="3.965225"
+     y="14.676847"
+     id="text4140"
+     sodipodi:linespacing="125%"><tspan
+       sodipodi:role="line"
+       id="tspan4142"
+       x="3.965225"
+       y="14.676847"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:7.5px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:start;writing-mode:lr-tb;text-anchor:start">360°</tspan></text>
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/link.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/link.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/link.svg	(revision 34317)
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+  <path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z" fill="#fff"/>
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/mapmode/mapillary-join.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/mapmode/mapillary-join.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/mapmode/mapillary-join.svg	(revision 34317)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24px" width="24px" version="1.1">
+  <path d="M0,0 h24 v24 h-24z" fill="#35af6d"/>
+  <path d="M17 20.41L18.41 19 15 15.59 13.59 17 17 20.41zM7.5 8H11v5.59L5.59 19 7 20.41l6-6V8h3.5L12 3.5 7.5 8z" fill="#fff" transform="translate(12,12) scale(.8) translate(-12,-12)"/>
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/mapmode/mapillary-select.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/mapmode/mapillary-select.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/mapmode/mapillary-select.svg	(revision 34317)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24px" width="24px" version="1.1">
+  <path d="M0,0 h24 v24 h-24z" fill="#35af6d"/>
+  <path d="M 13,6L 13,11L 18,11L 18,7.75L 22.25,12L 18,16.25L 18,13L 13,13L 13,18L 16.25,18L 12,22.25L 7.75,18L 11,18L 11,13L 6,13L 6,16.25L 1.75,12L 6,7.75L 6,11L 11,11L 11,6L 7.75,6L 12,1.75001L 16.25,6.00001L 13,6 Z" fill="#fff" transform="translate(12,12) scale(.8) translate(-12,-12)"/>
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/mapmode/streetside-join.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/mapmode/streetside-join.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/mapmode/streetside-join.svg	(revision 34317)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24px" width="24px" version="1.1">
+  <path d="M0,0 h24 v24 h-24z" fill="#35af6d"/>
+  <path d="M17 20.41L18.41 19 15 15.59 13.59 17 17 20.41zM7.5 8H11v5.59L5.59 19 7 20.41l6-6V8h3.5L12 3.5 7.5 8z" fill="#fff" transform="translate(12,12) scale(.8) translate(-12,-12)"/>
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/mapmode/streetside-select.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/mapmode/streetside-select.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/mapmode/streetside-select.svg	(revision 34317)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24px" width="24px" version="1.1">
+  <path d="M0,0 h24 v24 h-24z" fill="#35af6d"/>
+  <path d="M 13,6L 13,11L 18,11L 18,7.75L 22.25,12L 18,16.25L 18,13L 13,13L 13,18L 16.25,18L 12,22.25L 7.75,18L 11,18L 11,13L 6,13L 6,16.25L 1.75,12L 6,7.75L 6,11L 11,11L 11,6L 7.75,6L 12,1.75001L 16.25,6.00001L 13,6 Z" fill="#fff" transform="translate(12,12) scale(.8) translate(-12,-12)"/>
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/reload.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/reload.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/reload.svg	(revision 34317)
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="24"
+   height="24"
+   viewBox="0 0 24 24"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="reload.svg">
+  <metadata
+     id="metadata10">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs8" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1440"
+     inkscape:window-height="806"
+     id="namedview6"
+     showgrid="false"
+     inkscape:zoom="9.8333333"
+     inkscape:cx="20.046875"
+     inkscape:cy="19.254237"
+     inkscape:window-x="0"
+     inkscape:window-y="1"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2" />
+  <path
+     d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76 0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76 0 5-2.24 5-5s-2.24-5-5-5z"
+     fill="#fff"
+     id="path4" />
+  <text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.5px;line-height:100%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;-inkscape-font-specification:'sans-serif, Normal';font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;"
+     x="12.101695"
+     y="12"
+     id="text3338"
+     sodipodi:linespacing="100%"><tspan
+       sodipodi:role="line"
+       id="tspan3344"></tspan></text>
+  <text
+     xml:space="preserve"
+     style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:center;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+     x="11.389831"
+     y="13.220339"
+     id="text3346"
+     sodipodi:linespacing="125%"><tspan
+       sodipodi:role="line"
+       id="tspan3348"
+       x="11.389831"
+       y="13.220339"> RELOAD</tspan></text>
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/streetside-logo.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/streetside-logo.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/streetside-logo.svg	(revision 34317)
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   viewBox="0 0 100 100"
+   height="256"
+   width="256"
+   version="1.1"
+   id="svg2"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="streetside-logo.svg">
+  <metadata
+     id="metadata12">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs10" />
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1440"
+     inkscape:window-height="806"
+     id="namedview8"
+     showgrid="false"
+     inkscape:zoom="0.65186406"
+     inkscape:cx="-121.74619"
+     inkscape:cy="128"
+     inkscape:window-x="0"
+     inkscape:window-y="1"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2" />
+  <path
+     d="M0,0 h100 v100 h-100z"
+     fill="#35af6d"
+     id="path4"
+     style="fill:#a0e6f0;fill-opacity:1" />
+  <image
+     y="5.7182755"
+     x="7.5895896"
+     id="image4221"
+     xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxAOEA8PDg8RDw0VEBETDw4ODw8OEBAVFhIXFhUR
+FhUYHSggGBolGxcVIjEhMSkrLi4wFx8zODMsOCgtLisBCgoKDQ0OGg0NFTEZFSA3Ky03KzcrNys3
+ODcrKysrKys4KzcrLSsrKzc0KystMjc3Ky0yLSsrNys3ODM3LTUtK//AABEIAOEA4QMBIgACEQED
+EQH/xAAcAAACAgMBAQAAAAAAAAAAAAAABwECAwYIBQT/xABMEAABAwIBBwISBwYGAwEAAAABAAID
+BBEFBgcSITFBURNhCBQVFiIyM1NUcXJzgZGho7LSI0JSgpKxsxc1YnTBwiRDk6LR4URV8CX/xAAX
+AQEBAQEAAAAAAAAAAAAAAAAAAQQC/8QAHhEBAAEEAgMAAAAAAAAAAAAAAAEEEhMxA/ACMlH/2gAM
+AwEAAhEDEQA/AHihC+LFsSjpY3SyuDWgX1oPqllawEuIA4laxiWWsEZLYvpDxHa+tLPKrLeSrcQC
+WQ37FgO3nd/wtWfix4oG3NlpI7Y7Q8m1/avm66pfCJPdfKlX1VPFHVU8UDU66ZfCJPc/Kjrpl8Ik
+9z8qVfVU8UdVTxQNTrpl8Ik9z8qOumXwiT3PypV9VTxR1VPFA1OumXwiT3Pyo66ZfCJPc/KlX1VP
+FHVU8UDU66ZfCJPc/Kjrpl8Ik9z8qVfVU8UdVTxQNTrpl8Ik9z8qOumXwiT3PypV9VTxR1VPFA1O
+umXwiT3Pyo66ZfCJPc/KlX1VPFHVU8UDU66ZfCJPc/Kjrpl8Ik9z8qVfVU8UdVTxQNTrpl8Ik9z8
+qOumXwiT3PypV9VTxR1VPFA1OuqXwiT3Xyr6Ics5G7X6flBv9LJR9VTxR1VPFA9MPy4heQ2XsD9r
+a3/pbRT1DJAHMcHNOwg3XMgxU8VsWTGWktG8WcXRX7KMnV4xwKB/IXm4FjMVbE2WJ1wRrG8HeDzr
+0kAhCEFXvDQSdgSJzmZVmpndCx30MZtYbHOG0+jZ60084GLdKUUrwbO0SG+M6h7VzTUSl5JJvzoC
+WoJWEvKLIsgjTKNMqbIsgjTKNMqbIsgjTKNMqbIsgjTKNMqbIsgjTKNMqbIsgjTKNMqbIsgjTKNM
+qbIsgjTKNMqbIsgjTKNMqbIsgjTKNMqbIsgjTKyRzkKlkWQb3m7yrdR1DWud9A8hrwdgOwO/+/ou
+g4JQ9ocNhF1yJG7RK6MzXYwauhj0jd7Bou49jqug3JCEIFXnzqi2CGMbHSC/oa4/0SVsnBn12U/n
+P7HJRWQUsiyvZFkFLIsr2RZBSyLK9kWQUsiyvZFkFLIsr2RZBSyLK9kWQUsiyvZFkFLIsr2RZBSy
+LK9kWQUsiyvZFkFLIsr2RZBSyLK9kWQUsm5mKqT/AIiMnVpAj0t/6SmsmhmN7tP938igdaEIQKLP
+psp/Of2OSjsm5ny2U/nP7HJS2QVsiytZFkFbIsrWRZBWyLK1kWQVsiytZFkFbIsrWRZBWyLK1kWQ
+VsiytZFkFbIsrWRZBWyLK1kWQVsiytZFkFbIsrWRZBWyLK1kWQVsmfmP7tP938illZM7Mh3af7v5
+FA6UIQgUefLZT+c/sclKm1ny2U/nP7HJTIIQpQghClCCEKUIIQpQghClCCEKUIIQpQghClCCEKUI
+IQpQghClCCEKUIITNzI92n+7+RSzTMzI92n+7+RQOlCEIFHny2U/nP7HJX4XQPqpoqeLREkj2sYX
+ktbc7LkAkD0Ji9EJUOijpnNtflgNesEcm9L/ADdYk2TE8PaQWv6ai1bQey4oNtmzS4mxrnl9HZrS
+42nmvYC5t9EtDBvrXVuI9xm80/4SuUGdqPEEF0L7KDCamp109NPOPtQwySN/EBYL0xkRih19IT/h
+aPZdB4CF6Vbk/W09zNR1MbRte6CTQH3gLe1eYDfYglffgmES1sohhtexc5ziQ1jQQC4+sal8C9TJ
+3G30E3KsaHgt0ZIybBzbg6juNxtXHJfZOP2deFt0X6bPLm2eG9hVNMnB0Ra081w4keorSqylfBI+
+KVujIxxa5u2x/wCEwJc5EWj2FNIZLag5zAy/jFz7FoOI1r6iWSaS3KPdpOsLAbgBzAAD0LLSTUzM
+59d+NFRHBERi2+dCFLGlxDWgucdjWguceYAbVtZUIXtUuSOJSi7KCptxfE6L47LJNkXijBd1BUW/
+hZyh9TSSg8FCyVNPJC7QmjfE/wCxKx0bvwuAKxoBCEIBCtFG57gxjS952MYC5x8QGsr2qfI7E5Bd
+lBU2/jiMXsfZB4aF7dTkfiUQu+gqbb9CIy/BdeM6JwfyZa4SXA5MtIfc7G6O2/MgqhbVhWbvFKkB
+zaUwsOx1S4Q/7Dd4/CpykzfVuG05qql9LyIcxpEUszn3cbDU6MC3pQaomZmR7tP938il/U4XIGSP
+gdFVFnSmk2EygjpsXg1SMbe923ts0289t+zJwyRVlfDMWGSKbk3GM3ZdtwS07xzoHWhCECT6I3uV
+N54fpvSuzafvjDf5uL4k0eiN7lTeeH6b0rs2n74w3+bi+JB1xVQ6bHsBsXMc29r2uLXWnYFkDhmF
+RctOGTPjbeSrrNDQbba4NPYRjn285W7LmLPJlzLiNXJSRPLcPgkcxrGmwmkabOldx13DeAF95QND
+F89OHQuMVI11U5urSuKeHVqs1zhc/htzrxnZ56gm4oYQ3gZpCfXo/wBEg1kimeztXFviOr1IOjsK
+zyQPIFXSSQg7ZIXido5yCGut4gStlq8BwnHIuWayKXS1CppyI5mngSNdx9lwPiXK8WKyjbZ3jFj7
+FseSGXkuGVDZ42u0LgTxNcCyZm9pB3jWQdx5iQQ2rLjIGfCvpWnl6ImwmAs6Mk6myN3cA7Yea4C8
+rIunZLiNFHKxskbp2Nex7Q5rgb3BB1ELo+GSGtp2vAEtLPCHAOF2vjkbfWOcFIukwluHZRU9Jpdi
+2qjdDpHsnRvGkzxkA2J4tKBtVGRGFta97aCn0gxxF4wQDY7jqXN8fagngPyXWFYfo5PId8JXOGbr
+C21mIUcMg0otLlJGnYRGwv0TzEgA+NBtuQ+a41LGVOIl0ULgHR0zOxle3c57vqA8Br5wmDVVmFYD
+GBaGmuOxjjbpTy89hdzvKPrXrZRYj0pSVNSBpOihke1p2FzWktB5r2XMdZVSTyPmne6WZ5u+R5uX
+H+g4DYEDVxDPM0G1NQuc3c6ombGfwsDvzWClzzvuOWoGlu8xVBB9Tma/WlXZFkHQuDZX4XjLeQdo
+8o7/AMSsYzSd5IN2v9BJWv5WZpoZGulw08jNrPSz3F0L+ZpOth9Y3WG1Jq3/ACDwPFdBZq8ekrqA
+GdxfNFK6F8ju2eA1rmuPE6LwCd5BQICogfE98cjSyRji17HCzmuBsQQt7zf5uXYg1tVVl0VEe5sb
+2Ms/8V/qs59p3W1E+tnQwCKTGMMHaitcI5bai7knsD3XG8se0fdCbkUbWNaxjQ1jQGtaAAGgCwAH
+BBr1XU4ZgMAOjHTMOprI26U0xH+552XJPjK0euzz6/8ADUPY7nVEwa70tYCB+IpUZW5aOxCrmqXN
+c4OcREHGwjiBOgwDxazzknevAlxaU7NFviFz7UD3oM8+v/E0JDN7qeYOd+F4A/3Jg5P45Q4o0VNI
++OZzOxJ0Ry0JO1rgdbb+o23rjyWd7+2cT4zq9S9/N9lFLhmIU88biIzI2OoZukic4B4I5to5wEHU
+mVmUTMLpnVc0M80LSBJ0qxkjmA/XcHOb2N9/OkznMzq0GLYfJR00NWyV0kTg6eOFrLNdc62yE+xP
+upp2SsfFI0Pie1zHscLtc1ws5pG8EErjPKXDhSVlXTNN2w1E0TSdZIY8tB9QCDLS5SVcJcYpdBzm
+RMJa1t7RU7oI920McdfEA7QCmxmCqnz1FZLIQZHyBziAACSDfUNiSCdHQ69vU+U38igfaEIQJPoj
+e5U3nh+m9KfIGqbDimHSPNmCrg0jsABeBpHmF7psdEb3Km88P03pFIO4SuKMVo30888Et+Vjlkjk
+ve5c1xBPsXSOaPOHHikDKWpeG4lGyzg4gdMtaNUreLrdsONzs2ednbzWnEXGuw/RFbo/TQOIa2ps
+LBzXHU19hbXqOrWLaw51RZfViGHzUsjoamJ8Ew2xyscxw57HdzrBZBWyLLLFE57gxjS95NmsYC5z
+jwAGspwZr80cz5I63FYzFA0tfFRv1SSuGsGVv1Gj7J1neANoNvN/SPgwrDopQRI2li0mu1FpLQdE
+jcRe3oSvyxqWSZYYc1hBMfSrJLbnXe+34XtTKy8yzp8GpzLKQ+ocCKemDgHzO/owb3buckA88ZD1
+8tVj1FUzu05pa0PkdzuJNhwA2AbgAg6mru5S+bf8JXN2YPXjEdyTamnI1mw1NH9V0jXdyl82/wCE
+rm/MF++Gfy0/5NQO7OibYPiJGo9Lu1jUdoXKPTcnfH/iK6tzpfubEv5d35hcnWQZOm5O+P8AxFVN
+Q/7b/wAblWyLIAyOO1zj43EroPocv3dV/wA879CJc+WXQnQ5/u6r/nnfoRIMOfjEnUc+B1TBd0NT
+NIG/aDTCS30gW9KaOEYnDWQRVNO8SQSMD2OHA7iNxBuCNxBCUHRK9phfl1XwxJe5BZwavBXFsf09
+G43kpJHFrSftsdY6DuexB3g6rBOdDIqXCKyQhh6Rlkc6llaDoAOJPIk7nN1i28C/i0yy6hwvOVgm
+KRGKolji0m2kpsRaxjDzaTvo3eu6+KrzQ4FV3kg04gTf/C1IczjqD9IDxBBzVZbzmmyLmxStilLC
+KCCVsk8pHYuLSHCFv2nE2vwBJ4XcGHZn8Ep3NMjZKh1xotqajsSdw0WaId4ta3+CmZBEI6eJjGMa
+RFCwCKMW2NFhZovzIMOOYtDQ081VUvDIY2FzibXPBo4uJsAN5IXG+L17quoqKl4s+aaSVwvexe8u
+IvzXW7Z3sexWpqul8ShdSQsOlBStJdC7dywk2TGxtpbtYsDdL+yCqc/Q69vU+U38ikynN0OvdKny
+m/CgfaEIQJPojO5U3nh+m9IsBPXoi+5U3nh+m9IxBaGRzHNexzmPaQ5r2Etc0g3DgRrBHFNTJTPd
+WUwbFXxCtiFhyoIiqAL7SbaL9XMDxKVSkBB0gM6WT2IMDK0AA/5VdRmVoPjaHt9N1iLcjnEP/wDz
+r8L6A9LdQ9i51spsg6Qhy9yZw2/Shga+2sUVG8Od43hgB9a1TKTPtI8FmG0vJXGqoqi17x4om9iD
+zlx8STdlNkH0YniM9XK6eqmfPM7tpJHFx8Q4AbgNQX3ZIYmyir6OqlDjFFM17xGAXkC+wEgE+leT
+ZTZB0FUZ8MMex7RDW3LXAXihtrFu+JS5sco4cJr21dS2R0QhkYRC1rn3da2okC2ritXspsgdmWed
+3D6/D6ukhiqmyyxFjDJHEGAkjaQ8kD0JIWV7IsgrZRZXsiyClk0s1GcWjwalngqo6h731JlaYGRv
+bomNjbEucNd2lLCyLIGHndy7pcabRilZOzkXTF/LsYy+mGAW0XG/alLiyyNaSQBrJIAHEnYF7/WN
+i3/rKv8A0HINcsoDeGrxal9VbRyQSPhnjfFMw2fHI0te02vYg8xHrWCyDGRv38d6bmaLOZPFPFh9
+fK6emleI4JpXF8kL3GzGlx1uYSQNfa3G5Kay9PJfDpKutpKeG/KPnjALdrQHBzn/AHWgu9CDqbLf
+JWHF6SSmmAEliaea13QyW7F45uI3hcjVVM+GSSKQaMjHuY9vBzXFrh6wV2yuOcraplRiFfPEQYpK
+uofGW6w5pkcQ4eMa/Sg8eycnQ7d0qfKZ8KTlk4+h37pU+Uz4UD6QhCBKdEV3Km88P03pHAJ5dET3
+Om88P03pH2QRZTZSApAQRZTZTZWsgrZTZWspsgrZTZWspsgpZTZWspsgpZTZWspsgpZFleyLIrHZ
+FleyLIjGWp55rc6kTo4qHFJOTmYAyGrkPYStAs1srj2rwPrHU7jfaj7IIQdN5fZuqXGgJg/kKwNA
+ZUxtDw9u5sjfrjgbgjjbUk9ieZ3GIXWjhiqm3NnwTxs1biRKWke1eBgOV+I4eA2krJY4x/kuIlh9
+EbwQ30WW2wZ7cWaAHR0UnEugma4/hkA9iD4sMzN4xM60sUVKy4u6eeN5tvIbEXX8RsnFkFm8pMEa
+6XS5erLbSVUgDA1u0tY36jdVzrJO87AFTUZ7cWcCGso4+BZBMSPxSEexafj+V2IYjcVlXLLH3kER
+Q/6bAGn0goGlnWzqxGKSgwuTlHvBZPWRnsGNOpzInfWcRq0hqAOq52I2yvZRZBSycXQ8d0qvKZ8K
+T5CcHQ890qvKZ8KB8oQhAleiJ7nTeeH6b0kQE7+iI7nS+eH6b0kQEBZSApAVgEEAKQFICsAggBTZ
+SApAQRZTZWspARVbIsr2U2QUsiyvZTZBj0UWWSyLIjHZRZZLIsisdlFlksosgx2UWWSyghBjIVSF
+kIUEIMZCiyuQoIRGOyb/AEPXdarymfClEQm90PfdarymfCge6EIQJfohmnk6Y7uWH6b0kguhc+2H
+mWi5QDWwtd6AdfsuufAEAArAIAVgEEAKwCkBSAigBSApAVgEEAKQFYBWAQUspsrgKbIKWU2V7KbI
+MdkWWSyLIMVlFll0VFkGKyghZSFBCDEQoIWQhVIQYyFUhZCFBCDEQoIWQhVIRGMhN3ofB9JUn+Jv
+wpSEJ5ZgsOLIJZiLabyR6OxH5IG+hCEHkZUYaKqmliIvdp1ehcoYth7qWeSB4ILHEC+8biuxiEoM
+7uQxmHTVO36Ru0AdsN4QI4KwCCC0lrgWuBsQdRBVggkBWAUBWCKkBWAQArBAAKwCAFYBBACsArAK
+wCCllOir2U2RGPRRorLZRZBisoIWWyghFYSFBCykKhCDGQqkLIQqkIMZCqQshCoUFCFQhZCqE7hr
+O4DWSgyUdK6eRkTBd73Botu511RkPg4oqSKIC1mj8ktM0WQzg4VdS2zvqNI7UJ1tFhYbERKEIQCx
+zRNe0tcLg7brIqvbcWQKLODm2inLpqZwZLzW18xSaxTCailcWysNh9ZusLqPEMn3SkkSELXcQzdc
+tfSkJQc29MKRUp4VeZkP1iQepfA7Mi7dIPUgUAqVPTSbTsyUnfB6ljOZKXvg9SBVCr51IrOdNI5k
+5u+D1KpzKT98CBYis51PTvOmWcys/fAo/YrUd8CBbdO86np4cUx/2K1HfAj9itR3wIFx08OKOnhx
+TH/YrUd8CP2K1HfAgW/TvOo6d50yv2K1HfApGZWfvgQLM1nOoNZzpnjMpP3wKwzJzd8HqQKw1fOo
+NVzprDMlL3wepZG5kpO+D1IFIalVNSnC3Mi7fIPUvtpcy4brMg9SBP4dh09S4NiYTf6x1BN3IDNr
+GxzZqpwe/UQDsHiC2PD824htoyLYqDJx0RH0hPpQe/TQNjaGsADQNVllVImaIAV0AhCEAhCEAhCE
+AhCEAhCEAhCEEFCEIBCEIBCEIBCEIJKEIQCEIQCEIQCEIQCEIQCEIQf/2Q==
+"
+     preserveAspectRatio="none"
+     height="87.890625"
+     width="87.890625" />
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/images/unknown-mapobject-type.svg
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/images/unknown-mapobject-type.svg	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/images/unknown-mapobject-type.svg	(revision 34317)
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   viewBox="0 0 100 100"
+   height="100px"
+   width="100px"
+   version="1.1"
+   id="svg3514"
+   inkscape:version="0.91 r13725"
+   sodipodi:docname="unknown-mapobject-type.svg">
+  <metadata
+     id="metadata3526">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <defs
+     id="defs3524">
+    <filter
+       style="color-interpolation-filters:sRGB;"
+       inkscape:label="Invert"
+       id="filter3528">
+      <feColorMatrix
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
+         result="fbSourceGraphic"
+         id="feColorMatrix3530" />
+      <feColorMatrix
+         result="fbSourceGraphicAlpha"
+         in="fbSourceGraphic"
+         values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+         id="feColorMatrix3532" />
+      <feColorMatrix
+         id="feColorMatrix3534"
+         type="hueRotate"
+         values="180"
+         result="color1"
+         in="fbSourceGraphic" />
+      <feColorMatrix
+         id="feColorMatrix3536"
+         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 -0.21 -0.72 -0.07 2 0 "
+         result="color2" />
+    </filter>
+  </defs>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1440"
+     inkscape:window-height="795"
+     id="namedview3522"
+     showgrid="false"
+     inkscape:zoom="5.93"
+     inkscape:cx="50"
+     inkscape:cy="50"
+     inkscape:window-x="0"
+     inkscape:window-y="1"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg3514" />
+  <circle
+     cx="50"
+     cy="50"
+     r="50"
+     fill="#35af6d"
+     stroke="none"
+     id="circle3516"
+     style="filter:url(#filter3528)" />
+  <path
+     d="M30,35C30,25 40,15 50,15C60,15 70,25 70,35 C70,50 50,50 50,65L50,75"
+     fill="none"
+     stroke="#fff"
+     stroke-width="12"
+     id="path3518" />
+  <path
+     d="M50,86m-6,-6h12v12h-12z"
+     fill="#fff"
+     id="path3520" />
+</svg>
Index: applications/editors/josm/plugins/MicrosoftStreetside/ivy.xml
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/ivy.xml	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/ivy.xml	(revision 34317)
@@ -0,0 +1,12 @@
+<ivy-module version="2.0">
+	<info organisation="org.openstreetmap.josm.plugins" module="MicrosoftStreetside" revision="0.0.1" />
+	<configurations defaultconf="default" defaultconfmapping="default->default">
+		<conf name="default" />
+	</configurations>
+	<dependencies>
+		<dependency org="com.fasterxml.jackson.core" name="jackson-core" rev="2.2.4"/>
+        <dependency org="com.fasterxml.jackson.core" name="jackson-databind" rev="2.2.4"/>
+        <dependency org="com.fasterxml.jackson.core" name="jackson-annotations" rev="2.2.4"/>
+        <dependency org="us.monoid.web" name="resty" rev="0.3.2"/>
+	</dependencies>
+</ivy-module>
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/be.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/be.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/be.po	(revision 34317)
@@ -0,0 +1,461 @@
+# Translations for the JOSM plugin 'MS-Streetside-JOSM-Plugin' (be)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the ms-streetside-josm-plugin and Mapillary packages.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: ms-streetside-josm-plugin (based on Mapillary v1.5.10)\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: floscher, 2018\n"
+"Language-Team: Belarusian (https://www.transifex.com/josm/teams/2544/be/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: be\n"
+"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
+
+msgid "2 images joined"
+msgstr "2 выявы аб''яднаныя"
+
+msgid "2 images unjoined"
+msgstr "2 выявы раз''яднаныя"
+
+msgid ""
+"An exception occured while trying to submit a changeset. If this happens "
+"repeatedly, consider reporting a bug via the Help menu. If this message "
+"appears for the first time, simply try it again. This might have been an "
+"issue with the internet connection."
+msgstr ""
+"Адбылася абмыла пры спробе адправіць пакет правак на сервер. Калі яна "
+"ўзнікае перыядычна, можаце адправіць справаздачу пра памылку праз меню "
+"Даведка. Калі гэта паведамленне з''явілася ўпершыню, проста паспрабуйце яшчэ"
+" раз: магчыма гэта была праблема з падлучэннем да Інтэрнэту."
+
+msgid "Cancel"
+msgstr "Скасаваць"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr ""
+"Не атрымалася адправіць пакет правак па версіі пратакола {0} з абмылай: "
+"''{1} {2}''!"
+
+msgid "Choose signs"
+msgstr "Выберыце знакі"
+
+msgid "Continues with the paused walk."
+msgstr "Працягвае прыпынены шпацыр."
+
+msgid "Current Mapillary changeset"
+msgstr "Бягучы пакет правак Mapillary"
+
+msgid "Current Streetside changeset"
+msgstr "Бягучы пакет правак Streetside"
+
+msgid "Days"
+msgstr "Дні"
+
+msgid "Delete after upload"
+msgstr "Выдаліць пасля адпраўкі"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Паказваць час, калі быў зроблены здымак"
+
+msgid "Download Mapillary images in current view"
+msgstr "Сцягнуць здымкі Mapillary для бягучага віду"
+
+msgid "Download Streetside images in current view"
+msgstr "Сцягнуць здымкі Streetside для бягучага віду"
+
+msgid "Download mode"
+msgstr "Рэжым спампоўкі"
+
+msgid "Downloaded images"
+msgstr "Загружаныя здымкі"
+
+msgid "Downloading"
+msgstr "Сцягванне"
+
+msgid "Downloading Mapillary images"
+msgstr "Загрузка здымкаў Mapillary"
+
+msgid "Downloading Streetside images"
+msgstr "Загрузка здымкаў Streetside"
+
+msgid "Explore"
+msgstr "Агляд"
+
+msgid "Export all images"
+msgstr "Экспартаваць ўсе здымкі"
+
+msgid "Export selected images"
+msgstr "Экспартаваць выдзеленыя здымкі"
+
+msgid "Export selected sequence"
+msgstr "Экспартаваць выбраную паслядоўнасць"
+
+msgid "Finished upload"
+msgstr "Адсылка скончана"
+
+msgid "Follow selected image"
+msgstr "Прытрымлівацца вылучанага здымка"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Даць дарогу"
+
+msgid "Go forward"
+msgstr "Ісці наперад"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr "Перайсці да налад і ўвайсці ў Mapillary перад адпраўкай дадзеных."
+
+msgid "Go to setting and log in to Streetside before uploading."
+msgstr "Перайсці да налад і ўвайсці ў Streetside перад адпраўкай дадзеных."
+
+msgid "I got it, close this."
+msgstr "Мне гэта зразумела, зачыніце."
+
+msgid "Import"
+msgstr "Імпартаваць"
+
+msgid "Import local pictures"
+msgstr "Імпартаваць лакальныя выявы"
+
+msgid "Import pictures"
+msgstr "Імпартаваць выявы"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Імпартаваць выявы на пласт Mapillary"
+
+msgid "Imported images"
+msgstr "Імпартаваныя выявы"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Перакрыжаванне з другаснай"
+
+msgid "Join mode"
+msgstr "Рэжым злучэння"
+
+msgid "Join/unjoin pictures"
+msgstr "Злучыць/раз''яднаць выявы"
+
+msgid "Jump to blue"
+msgstr "Перайсці да сіняга"
+
+msgid "Jump to red"
+msgstr "Перайсці да чырвонага"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Перайсці да выявы на другім баку сіняй лініі"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Перайсці да выявы на другім баку чырвонай лініі"
+
+msgid "Key copied to clipboard"
+msgstr "Ключ скапіраваны ў буфер"
+
+msgid "Login"
+msgstr "Увайсці"
+
+msgid "Login successful, return to JOSM."
+msgstr "Уваход паспяхова выкананы, зварот у JOSM."
+
+msgid "Logout"
+msgstr "Выйсці"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Кірунак руху"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Microsoft Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Здымкі Mapillary"
+
+msgid "Microsoft Streetside Images"
+msgstr "Microsoft Здымкі Streetside"
+
+msgid "Mapillary changeset"
+msgstr "Пакет правак Mapillary"
+
+msgid "Streetside changeset"
+msgstr "Пакет правак Streetside"
+
+msgid "Mapillary filter"
+msgstr "Фільтр Mapillary"
+
+msgid "Streetside filter"
+msgstr "Фільтр Streetside"
+
+msgid "Mapillary history"
+msgstr "Гісторыя Mapillary"
+
+msgid "Streetside history"
+msgstr "Гісторыя Streetside"
+
+msgid "Mapillary layer"
+msgstr "Mapillary"
+
+msgid "Streetside layer"
+msgstr "Streetside"
+
+msgid "Mapillary login"
+msgstr "Уваход у Mapillary"
+
+msgid "Streetside login"
+msgstr "Уваход у Streetside"
+
+msgid "Months"
+msgstr "Месяцы"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr ""
+"Перамяшчацца да месцазнаходжання выявы пры націсканні кнопкак наперад/назад"
+
+msgid "Next picture"
+msgstr "Наступны здымак"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "Заезд забаронены"
+
+msgid "No image selected"
+msgstr "Выява не абрана"
+
+msgid "No images found"
+msgstr "Выявы не знойдзеныя"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "Абгон забаронены"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "Стаянка забаронена"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "Паварот забаронены"
+
+msgid "Not Logged in to Mapillary"
+msgstr "Не выкананы ўваход у Mapillary"
+
+msgid "Not Logged in to Streetside"
+msgstr "Не выкананы ўваход у Streetside"
+
+msgid "Not older than: "
+msgstr "Не старэйшыя за: "
+
+msgid "Only images with signs"
+msgstr "Толькі здымкі са знакамі"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Адкрыць дыялог набору змен Mapillary"
+
+msgid "Open Streetside changeset dialog"
+msgstr "Адкрыць дыялог набору змен Streetside"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Адкрыць дыялог фільтра Mapillary"
+
+msgid "Open Streetside filter dialog"
+msgstr "Адкрыць дыялог фільтра Streetside"
+
+msgid "Open Mapillary history dialog"
+msgstr "Адкрыць дыялог гісторыі Mapillary"
+
+msgid "Open Streetside history dialog"
+msgstr "Адкрыць дыялог гісторыі Streetside"
+
+msgid "Open Mapillary window"
+msgstr "Адкрыць акно Mapillary"
+
+msgid "Open Streetside window"
+msgstr "Адкрыць акно Streetside"
+
+msgid "Pause"
+msgstr "Прыпыніць"
+
+msgid "Pauses the walk."
+msgstr "Прыпыніць шпацыр."
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Пешаходны пераход"
+
+msgid "Play"
+msgstr "Прайграць"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Перадпрагляд выявы пры навядзенні на яго значок"
+
+msgid "Previous picture"
+msgstr "Папярэдні здымак"
+
+msgid "Redo"
+msgstr "Паўтарыць"
+
+msgid "Reset"
+msgstr "Скід"
+
+msgid "Rewrite imported images"
+msgstr "Перазапісаць імпартаваныя выявы"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Круг"
+
+msgid "Select a directory"
+msgstr "Выберыце каталог"
+
+msgid "Select mode"
+msgstr "Рэжым вылучэння"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Паказвае наступны здымак паслядоўнасці"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Паказвае папярэдні здымак паслядоўнасці"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Абмежаванне хуткасці"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Стоп"
+
+msgid "Stops the walk."
+msgstr "Cпыніць шпацыр."
+
+msgid "Submit changeset"
+msgstr "Перадаць пакет правак"
+
+msgid "Submit the current changeset"
+msgstr "Перадаць бягучы пакет правак"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "Перадаць бягучы пакет правак у Mapillary"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "Перадача пакета правак Mapillary"
+
+msgid "Submitting Streetside Changeset"
+msgstr "Перадача пакета правак Streetside"
+
+msgid "Submitting changeset to server…"
+msgstr "Адпраўка пакета правак на сервер…"
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Падтрымоўваныя фарматы малюнкаў (JPG і PNG)"
+
+msgid "Tag conflict"
+msgstr "Канфлікт у тэгах"
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Усяго здымкаў Mapillary: {0}"
+
+msgid "Total Streetside images: {0}"
+msgstr "Усяго здымкаў Streetside: {0}"
+
+msgid "Undo"
+msgstr "Вярнуць"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Няроўная дарога"
+
+msgid "Update"
+msgstr "Абнавіць"
+
+msgid "Upload selected sequence"
+msgstr "Адаслаць вылучаную паслядоўнасць"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Адсылаецца: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "Выкарыстоўваць 24-гадзінны фармат"
+
+msgid "User"
+msgstr "Карыстальнік"
+
+msgid "Wait for full quality pictures"
+msgstr "Чакаць якасных фатаграфій"
+
+msgid "Walk mode"
+msgstr "Пешаходны рэжым"
+
+msgid "Years"
+msgstr "Гады"
+
+msgid "You are currently not logged in."
+msgstr "Вы не выканалі ўваход."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "Вы ўвайшлі як ''{0}''."
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr "Не выкананы ўваход, увайдзіце ў Mapillary у Наладах"
+
+msgid "You are not logged in, please log in to Streetside in the preferences"
+msgstr "Не выкананы ўваход, увайдзіце ў Streetside у Наладах"
+
+#, java-format
+msgid "You have successfully uploaded {0} images to mapillary.com"
+msgstr "Вы паспяхова загрузілі {0} выяў на mapillary.com"
+
+msgid "You have successfully uploaded {0} images to streetside.com"
+msgstr "Вы паспяхова загрузілі {0} выяў на streetside.com"
+
+msgid "Zoom to selected image"
+msgstr "Маштабаваць да вылучанага здымка"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Наблізіцца да бягучага вылучанага здымка Mapillary"
+
+msgid "Zoom to the currently selected Streetside image"
+msgstr "Наблізіцца да бягучага вылучанага здымка Streetside"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "вобласці са спампаванымі дадзенымі OSM"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "усё ў бачнай вобласці"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "толькі пры запыце ўручную"
+
+msgid "pending"
+msgstr "у чаканні"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr ""
+"Дазваляе карыстальнікам працаваць з выявамі, размешчанымі на mapillary.com"
+
+#. Plugin description for Streetside
+msgid "Allows the user to work with pictures hosted at streetside.com"
+msgstr ""
+"Дазваляе карыстальнікам працаваць з выявамі, размешчанымі на streetside.com"
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/ca.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/ca.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/ca.po	(revision 34317)
@@ -0,0 +1,336 @@
+# Translations for the JOSM plugin 'Mapillary' (ca)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: floscher, 2018\n"
+"Language-Team: Catalan (https://www.transifex.com/josm/teams/2544/ca/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ca\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgid "2 images joined"
+msgstr "2 imatges afegides"
+
+msgid "2 images unjoined"
+msgstr "2 imatges tretes"
+
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgid "Choose signs"
+msgstr "Selecciona un senyal"
+
+msgid "Continues with the paused walk."
+msgstr "Continua amb la cminada pausada."
+
+msgid "Days"
+msgstr "Dies"
+
+msgid "Delete after upload"
+msgstr "Suprimeix un cop s''hagi pujat"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "Suprimida {0} imatge"
+msgstr[1] "Suprimides {0} imatges"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Mostra l''hora a la qual es van fer les fotografies"
+
+msgid "Download Mapillary images in current view"
+msgstr "Descarrega imatges de Mapillary a la vista actual"
+
+msgid "Download mode"
+msgstr "Mode de descàrrega"
+
+msgid "Downloaded images"
+msgstr "Imatges descarregades"
+
+msgid "Downloading"
+msgstr "Descarregant"
+
+msgid "Downloading Mapillary images"
+msgstr "Descarregant imatges de Mapillary"
+
+msgid "Explore"
+msgstr "Explora"
+
+msgid "Export all images"
+msgstr "Exporta totes les imatges"
+
+msgid "Export selected images"
+msgstr "Exporta les imatges seleccionades"
+
+msgid "Export selected sequence"
+msgstr "Exporta la seqüència seleccionada"
+
+msgid "Finished upload"
+msgstr "La pujada ha finalitzat"
+
+msgid "Follow selected image"
+msgstr "Segueix la imatge seleccionada"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Cediu el pas"
+
+msgid "Go forward"
+msgstr "Vés endavant"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr ""
+"Aneu a la configuració i inicieu una sessió de Mapillary abans de fer la "
+"pujada."
+
+msgid "Import"
+msgstr "Importa"
+
+msgid "Import local pictures"
+msgstr "Importa imatges locals"
+
+msgid "Import pictures"
+msgstr "Importa imatges"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Importa imatges a la capa de Mapillary"
+
+msgid "Imported images"
+msgstr "Imatges importades"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "Importada {0} imatge"
+msgstr[1] "Importades {0} imatges"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Intersecció"
+
+msgid "Join mode"
+msgstr "Afegeix mode"
+
+msgid "Join/unjoin pictures"
+msgstr "Afegeix/treu fotografies"
+
+msgid "Jump to blue"
+msgstr "Salta al blau"
+
+msgid "Jump to red"
+msgstr "Salta al vermell"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Salta a la fotografia de l''altra banda de la línia blava"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Salta a la fotografia de l''altra banda de la línia vermella"
+
+msgid "Login"
+msgstr "Inici de sessió"
+
+msgid "Login successful, return to JOSM."
+msgstr "Sessió iniciada correctament, retorn a JOSM."
+
+msgid "Logout"
+msgstr "Tanca la sessió"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Sentit obligatori"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Mapillary Images"
+msgstr "Imatges de Mapillary"
+
+msgid "Mapillary filter"
+msgstr "Filtre de Mapillary"
+
+msgid "Mapillary history"
+msgstr "Historial de Mapillary"
+
+msgid "Mapillary layer"
+msgstr "Capa de Mapillary"
+
+msgid "Mapillary login"
+msgstr "Inici de sessió de Mapillar"
+
+msgid "Months"
+msgstr "Mesos"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr "Mou a la ubicació de les fotografies amb els botons següent/previ"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "{0} imatge moguda"
+msgstr[1] "{0} imatges mogudes"
+
+msgid "Next picture"
+msgstr "Imatge següent"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "Entrada prohibida"
+
+msgid "No image selected"
+msgstr "No heu seleccionat cap imatge"
+
+msgid "No images found"
+msgstr "No s''ha trobat cap imatge"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "Avançament prohibit"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "Estacionament prohibit"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "Gir prohibit"
+
+msgid "Not older than: "
+msgstr "No anteriors a: "
+
+msgid "Only images with signs"
+msgstr "Només les imatges amb senyals"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Obre el diàleg de filtre de  Mapillary"
+
+msgid "Open Mapillary history dialog"
+msgstr "Obre el diàleg de l''historial de Mapillary"
+
+msgid "Open Mapillary window"
+msgstr "Obre una finestra de Mapillary"
+
+msgid "Pause"
+msgstr "Pausa"
+
+msgid "Pauses the walk."
+msgstr "Posa en pausa la caminada."
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Pas de vianants"
+
+msgid "Play"
+msgstr "Reprodueix"
+
+msgid "Previous picture"
+msgstr "Imatge anterior"
+
+msgid "Redo"
+msgstr "Refés"
+
+msgid "Reset"
+msgstr "Reinicia"
+
+msgid "Rewrite imported images"
+msgstr "Reescriu les imatges importades"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Rotonda"
+
+msgid "Select a directory"
+msgstr "Seleccioneu un directori"
+
+msgid "Select mode"
+msgstr "Seleccioneu el mode"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Mostra la següent imatge de la seqüència"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Mostra la imatge anterior de la seqüència"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Límit de velocitat"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Stop"
+
+msgid "Stops the walk."
+msgstr "Atura la caminada."
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Els formats de fitxer suportats  són JPG i PNG"
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Nombre total d''imatges de Mapillary: {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "{0} imatge girada"
+msgstr[1] "{0} imatges girades"
+
+msgid "Undo"
+msgstr "Desfés"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Perfil irregular"
+
+msgid "Update"
+msgstr "Actualitza"
+
+msgid "Upload selected sequence"
+msgstr "Puja la seqüència seleccionada"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Pujant: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "Utilitza un format de 24 hores"
+
+msgid "User"
+msgstr "Usuari"
+
+msgid "Wait for full quality pictures"
+msgstr "Espereu per a imatges de la màxima qualitat"
+
+msgid "Walk mode"
+msgstr "Mode caminant"
+
+msgid "Years"
+msgstr "Anys"
+
+msgid "You are currently not logged in."
+msgstr "Ara no esteu connectat."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "Esteu connectat com ''{0}''."
+
+msgid "Zoom to selected image"
+msgstr "Amplia la imatge seleccionada"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Amplia la imatge seleccionada de Mapillary"
+
+msgid "pending"
+msgstr "pendent"
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/cs.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/cs.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/cs.po	(revision 34317)
@@ -0,0 +1,661 @@
+# Translations for the JOSM plugin 'Mapillary' (cs)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: floscher, 2018\n"
+"Language-Team: Czech (https://www.transifex.com/josm/teams/2544/cs/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: cs\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+msgid "2 images joined"
+msgstr "2 obrázky sloučeny"
+
+msgid "2 images unjoined"
+msgstr "2 obrázky rozděleny"
+
+#, java-format
+msgid ""
+"A tag with key <i>{0}</i> is already present on the selected OSM object."
+msgstr "Značka s klíčem <i>{0}</i> je již na vybraném objektu OSM přítomna."
+
+msgid "Add Mapillary tag"
+msgstr "Přidat značku Mapillary"
+
+msgid "All images in a directory"
+msgstr "Všechny obrázky v adresáři"
+
+msgid "All map objects loaded."
+msgstr "Všechny objekty mapy načteny."
+
+msgid ""
+"An exception occured while trying to submit a changeset. If this happens "
+"repeatedly, consider reporting a bug via the Help menu. If this message "
+"appears for the first time, simply try it again. This might have been an "
+"issue with the internet connection."
+msgstr ""
+"Při pokusu o odeslání sady změn na server došlo k výjimce. Pokud k tomu "
+"dojde opakovaně, zvažte zaslání hlášení o chybě pomocí menu Nápověda. Pokud "
+"tuto zprávu vidíte poprvé, tak to prostě zkuste udělat znovu. Může se jednat"
+" o problém s připojením k Internetu."
+
+msgid "Cancel"
+msgstr "Zrušit"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr "Nahrání sady změn na server selhalo s {0} chybou ''{1} {2}''!"
+
+msgid "Choose signs"
+msgstr "Zvolit značky"
+
+msgid "Continues with the paused walk."
+msgstr "Pokračuje v pozastaveném průchodu."
+
+msgid "Copy key"
+msgstr "Kopírovat klíč"
+
+msgid "Could not import a geotagged image to the Mapillary layer!"
+msgstr ""
+"Nepodařilo se importovat obrázek se zem. souřadnicemi do vrstvy Mapillary!"
+
+#, java-format
+msgid "Could not import the directory ''{0}''!"
+msgstr "Nepodařilo se importovat adresář ''{0}''!"
+
+#, java-format
+msgid "Could not import the image ''{0}''!"
+msgstr "Nepodařilo se importovat obrázek ''{0}''!"
+
+#, java-format
+msgid "Could not open the URL {0} in a browser"
+msgstr "Nemohu otevřít URL {0} v prohlížeči"
+
+#, java-format
+msgid "Could not read from URL {0}!"
+msgstr "Nelze číst z URL {0}!"
+
+msgid "Current Mapillary changeset"
+msgstr "Aktuální sada změn Mapillary"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Cut off sequences at download bounds"
+msgstr "Useknout sekvence na hranicích stahování"
+
+msgid "Days"
+msgstr "Dnů"
+
+msgid "Delete after upload"
+msgstr "Smazat po nahrání"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "Smazán {0} obrázek"
+msgstr[1] "Smazány {0} obrázky"
+msgstr[2] "Smazáno {0} obrázků"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Zobrazit hodinu, kdy byl obrázek pořízen"
+
+msgid "Displays detail information on the currently selected Mapillary image"
+msgstr "Zobrazí podrobné informace o aktuálně zvoleném obrázku Mapillary."
+
+msgid "Displays objects detected by Mapillary from their street view imagery"
+msgstr "Zobrazí objekty detekované Mapillary z jejich fotografií ulic"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr "Zobrazí vrstvu, ve které jsou mapové objekty detekované Mapillary"
+
+#, java-format
+msgid ""
+"Do you really want to replace the current value <i>{0}</i> with the new "
+"value <i>{1}</i>?"
+msgstr ""
+"Opravdu chcete nahradit současnou hodnotu <i>{0}</i> novou hodnotou "
+"<i>{1}</i>?"
+
+msgid "Download Mapillary images in current view"
+msgstr "Stáhnout obrázky Mapillary v aktuálním zobrazení"
+
+msgid "Download mode"
+msgstr "Režim stahování"
+
+msgid "Downloaded images"
+msgstr "Stažené obrázky"
+
+msgid "Downloading"
+msgstr "Stahuji"
+
+msgid "Downloading Mapillary images"
+msgstr "Stáhnout obrázky z Mapillary"
+
+msgid "Downloading map objects failed!"
+msgstr "Stažení objektů mapy selhalo!"
+
+msgid "Downloading map objects…"
+msgstr "Stahuji objekty mapy..."
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr "Povolit experimentální beta-funkce (může být nestabilní)"
+
+msgid "Explore"
+msgstr "Prozkoumat"
+
+msgid "Export Mapillary images"
+msgstr "Exportovat obrázky Mapillary"
+
+msgid "Export all images"
+msgstr "Exportovat všechny obrázky"
+
+msgid "Export selected images"
+msgstr "Exportovat zvolené obrázky"
+
+msgid "Export selected sequence"
+msgstr "Exportovat vybranou sekvenci"
+
+msgid "Finished upload"
+msgstr "Nahrávání na server dokončeno"
+
+msgid "Follow selected image"
+msgstr "Následovat vybraný obrázek"
+
+msgid "From existing image layer"
+msgstr "Z existující vrstvy obrázků"
+
+msgid "From which source do you want to import images to the Mapillary layer?"
+msgstr "Z jakého zdroje chcete importovat obrázky do vrstvy Mapillary?"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Dej přednost"
+
+msgid "Go forward"
+msgstr "Vpřed"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr "Jděte do nastavení a před nahráváním se přihlašte na Mapillary."
+
+msgid "I got it, close this."
+msgstr "Rozumím, zavřít."
+
+msgid "Image actions"
+msgstr "Akce s obrázkem"
+
+msgid "Image detections"
+msgstr "Detekce obrázků"
+
+msgid "Image info"
+msgstr "Informace o obrázku"
+
+msgid "Image key"
+msgstr "Klíč obrázku"
+
+msgid "Images from my file system"
+msgstr "Obrázky z mého souborového systému"
+
+msgid "Import"
+msgstr "Import"
+
+msgid "Import exception"
+msgstr "Výjimka z importu"
+
+msgid "Import local pictures"
+msgstr "Import lokálních obrázků"
+
+msgid "Import pictures"
+msgstr "Importovat obrázky"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Importovat obrázky do vrstvy Mapillary"
+
+msgid "Imported images"
+msgstr "Importované obrázky"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "Importován {0} obrázek"
+msgstr[1] "Importovány {0} obrázky"
+msgstr[2] "Importováno {0} obrázků"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Upozornění na křižovatku"
+
+msgid ""
+"It can be activated by clicking the left button at the bottom of this "
+"message or the button in the toolbar on the left, which uses the same icon."
+msgstr ""
+"Lze ho aktivovat kliknutím levým tlačítkem na spodek této zprávy nebo "
+"tlačítkem na panelu nástrojů vlevo, které má stejnou ikonu."
+
+msgid "Join mode"
+msgstr "Režim slučování"
+
+msgid "Join/unjoin pictures"
+msgstr "Sloučit/rozdělit obrázky"
+
+msgid "Jump to blue"
+msgstr "Skočit na modrou"
+
+msgid "Jump to red"
+msgstr "Skočit na červenou"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Skočí na obrázek na druhé straně modré čáry"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Skočí na obrázek na druhé straně červené čáry"
+
+msgid "Key copied to clipboard"
+msgstr "Klíč zkopírován do schránky"
+
+msgid "Login"
+msgstr "Přihlásit se"
+
+msgid "Login successful, return to JOSM."
+msgstr "Přihlášení úspěšné, návrat do JOSM."
+
+msgid "Logout"
+msgstr "Odhlásit se"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Přikázaný směr jízdy (jakýkoliv)"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Obrázky Mapillary"
+
+msgid "Mapillary changeset"
+msgstr "Sada změn Mapillary"
+
+msgid "Mapillary filter"
+msgstr "Filtr Mapillary"
+
+msgid "Mapillary history"
+msgstr "Historie Mapillary"
+
+msgid "Mapillary image"
+msgstr "Obrázek Mapillary"
+
+msgid "Mapillary layer"
+msgstr "Vrstva Mapillary"
+
+msgid "Mapillary login"
+msgstr "Přihlášení Mapillary"
+
+msgid "Mapillary object layer"
+msgstr "Vrstva objektů Mapillary"
+
+msgid "Mapillary objects"
+msgstr "Objekty Mapillary"
+
+msgid "Months"
+msgstr "Měsíců"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr "Přesunout se na umístění obrázku tlačítky další/předchozí"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "Posunut {0} obrázek"
+msgstr[1] "Posunuty {0} obrázky"
+msgstr[2] "Posunuto {0} obrázků"
+
+msgid "Next picture"
+msgstr "Další obrázek"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "Zákaz vjezdu"
+
+msgid "No image selected"
+msgstr "Nebyl vybrán žádný obrázek"
+
+msgid "No images found"
+msgstr "Nebyly nalezeny žádné obrázky"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "Zákaz předjíždění"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "Zákaz parkování"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "Zákaz odbočení"
+
+msgid "Not Logged in to Mapillary"
+msgstr "Nepřihlášeno k Mapillary"
+
+msgid "Not older than: "
+msgstr "Ne starší než: "
+
+#. i18n: Spinner label in JOSM settings
+msgid "Number of images to be pre-fetched (forwards and backwards)"
+msgstr "Počet snímků, která se mají načíst dopředu (vpřed a vzad)"
+
+msgid "Only images with signs"
+msgstr "Pouze obrázky se značkami"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Otevřít dialog sady změn Mapillary"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Otevřít okno filtru Mapillary"
+
+msgid "Open Mapillary history dialog"
+msgstr "Otevřít dialog historie Mapillary"
+
+msgid "Open Mapillary layer"
+msgstr "Otevřená vrstva Mapillary"
+
+msgid "Open Mapillary window"
+msgstr "Otevřít okno Mapillary"
+
+msgid "Pause"
+msgstr "Pozastavit"
+
+msgid "Pauses the walk."
+msgstr "Pozastaví průchod."
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Přechod pro chodce"
+
+msgid "Play"
+msgstr "Přehrát"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "Stiskněte \"{0}\" pro stažení obrázků"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Nahlédnout obrázek při ukázání na jeho ikonu"
+
+msgid "Previous picture"
+msgstr "Předchozí obrázek"
+
+msgid "Redo"
+msgstr "Znovu"
+
+msgid "Reset"
+msgstr "Reset"
+
+msgid "Rewrite imported images"
+msgstr "Přepsat importované obrázky"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Kruhový objezd"
+
+msgid "Select a directory"
+msgstr "Zvolte adresář"
+
+msgid "Select directory to import images from"
+msgstr "Zvolte adresář, ze kterého chcete importovat obrázky"
+
+msgid "Select mode"
+msgstr "Výběr režimu"
+
+msgid "Select the images you want to import"
+msgstr "Zvolte obrázky, které chcete importovat"
+
+msgid "Sequence key"
+msgstr "Klíč sekvence"
+
+msgid "Show detections on top of image"
+msgstr "Zobrazit detekce na vrcholu snímku"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Ukáže další obrázek v sekvenci"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Ukáže předchozí obrázek v sekvenci"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Omezení rychlosti"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Stop"
+
+msgid "Stops the walk."
+msgstr "Ukončí průchod."
+
+msgid "Submit changeset"
+msgstr "Odeslat sadu změn"
+
+msgid "Submit the current changeset"
+msgstr "Odeslat aktuální sadu změn"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "Odeslat aktuální sadu změn na Mapillary"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "Odesílání sady změn Mapillary"
+
+msgid "Submitting changeset to server…"
+msgstr "Odesílám sadu změn na server…"
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Podporované formáty obrázků (JPG a PNG)"
+
+msgid "Tag conflict"
+msgstr "Konflikt značek"
+
+msgid ""
+"The Mapillary layer has stopped downloading images, because the requested "
+"area is too big!"
+msgstr ""
+"Do vrstvy Mapillary se již nenačítají obrázky, protože požadovaná oblast je "
+"příliš velká!"
+
+msgid ""
+"The Mapillary plugin now uses a separate panel to display extra information "
+"(like the image key) and actions for the currently selected Mapillary image "
+"(like viewing it in a browser)."
+msgstr ""
+"Doplněk Mapillary nyní používá zvláštní panel pro zobrazení dodatečných "
+"informací (jako třeba klíče image) a akcí s aktuálně zvoleným obrázkem z "
+"Mapillary (jako třeba zobrazení v prohlížeči)."
+
+msgid "There are currently no layers with geotagged images!"
+msgstr ""
+"Momentálně nemáme žádné vrstvy s obrázky se zeměpisnými sourřadnicemi!"
+
+#, java-format
+msgid ""
+"To solve this problem, you could switch to download mode ''{0}'' and load "
+"Mapillary images for a smaller portion of the map."
+msgstr ""
+"Chcete-li tento problém vyřešit, přepněte na režim stahování ''{0}'' a "
+"načtěte obrázky Mapillary z menší části mapy."
+
+msgid ""
+"To solve this problem, you could zoom in and load a smaller area of the map."
+msgstr ""
+"Chcete-li tento problém vyřešit, přibližte obraz a načtěte menší oblast "
+"mapy."
+
+msgid "Too many map objects, zoom in to see all."
+msgstr ""
+"Příliš mnoho mapových objektů, zvětšte přiblížení, abyste viděli všechny."
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Celkem obrázků z Mapillary: {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "Otočen {0} obrázek"
+msgstr[1] "Otočeny {0} obrázky"
+msgstr[2] "Otočeno {0} obrázků"
+
+msgid "Undo"
+msgstr "Zpět"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Nerovnost vozovky"
+
+msgid "Update"
+msgstr "Aktualizovat"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Nahrávám na server: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "Použít 24hodinový formát"
+
+msgid "User"
+msgstr "Uživatel"
+
+msgid "View in browser"
+msgstr "Zobrazit v prohlížeči"
+
+msgid "Wait for full quality pictures"
+msgstr "Počkat na obrázek v maximální kvalitě"
+
+msgid "Walk mode"
+msgstr "Režim chůze"
+
+#. i18n: Checkbox label in JOSM settings
+msgid ""
+"When opening Mapillary image in web browser, show the blur editor instead of"
+" the image viewer"
+msgstr ""
+"Při otevírání obrázku Mapillary v internetovém prohlížeči zobrazit namísto "
+"prohlížeče obrázků editor rozmazání."
+
+msgid "Which image layers do you want to import into the Mapillary layer?"
+msgstr "Které vrstvy obrázků chcete importovat do vrstvy Mapillary?"
+
+msgid "Years"
+msgstr "Let"
+
+msgid "You are currently not logged in."
+msgstr "Momentálně nejste přihlášen."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "Jste přihlášen jako ''{0}''."
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr "Nejste přihlášeni, prosím, přihlaste se k Mapillary v předvolbách"
+
+#, java-format
+msgid "You have successfully uploaded {0} images to mapillary.com"
+msgstr "Úspěšně jste nahrál {0} obrázky na mapillary.com"
+
+msgid "Zoom to selected image"
+msgstr "Zvětšit na zvolený obrázek"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Zvětšit na aktuálně zvolený obrázek Mapillary"
+
+msgid "approved"
+msgstr "schváleno"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "oblasti se staženými daty OSM"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "vše ve viditelné oblasti"
+
+msgid "image has no key"
+msgstr "obrázek nemá žádný klíč"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "pouze pokud je ručně požadováno"
+
+msgid "pending"
+msgstr "čekající"
+
+msgid "rejected"
+msgstr "zamítnuto"
+
+msgid "sequence has no key"
+msgstr "sekvence nemá žádný klíč"
+
+msgid "unknown user"
+msgstr "neznámý uživatel"
+
+#, java-format
+msgid ""
+"{0}\n"
+"Could not read map objects from URL\n"
+"{1}!"
+msgstr ""
+"{0}\n"
+"Nelze načíst objekty mapy z URL\n"
+"{1}!"
+
+#. i18n: {0} is the layer name, {1} the number of images in it
+#, java-format
+msgid "{0} ({1} images)"
+msgstr "{0} ({1} obrázků)"
+
+#, java-format
+msgid "{0} detections"
+msgstr "{0} detekcí"
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "{0} stažených obrázků"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "{0} obrázků celkem"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{0} obrázků ve {1} sekvencích"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr "{0} obrázků předáno, klíč sady změn: {1}, stav: {2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "{0} importovaných obrázků"
+
+#, java-format
+msgid "{0} sequences, each containing between {1} and {2} images (ø {3})"
+msgstr "{0} sekvencí, každá obsahuje mezi {1} a {2} obrázky (ø {3})"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr "Dovoluje uživateli pracovat s obrázky uloženými na mapillary.com"
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/da.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/da.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/da.po	(revision 34317)
@@ -0,0 +1,665 @@
+# Translations for the JOSM plugin 'Mapillary' (da)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Jurbo Lator <joern.map@gmail.com>, 2018\n"
+"Language-Team: Danish (https://www.transifex.com/josm/teams/2544/da/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: da\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgid "2 images joined"
+msgstr "2 billeder lagt sammen"
+
+msgid "2 images unjoined"
+msgstr "2 billeder adskilt"
+
+#, java-format
+msgid ""
+"A tag with key <i>{0}</i> is already present on the selected OSM object."
+msgstr ""
+"Et tag med nøgle <i>{0}</i> er allerede til stede på det valgte OSM objekt."
+
+msgid "Add Mapillary tag"
+msgstr "Tilføj Mapillary tag"
+
+msgid "All images in a directory"
+msgstr "Alle billeder i en mappe"
+
+msgid "All map objects loaded."
+msgstr "Alle kortobjekter er indlæst."
+
+msgid ""
+"An exception occured while trying to submit a changeset. If this happens "
+"repeatedly, consider reporting a bug via the Help menu. If this message "
+"appears for the first time, simply try it again. This might have been an "
+"issue with the internet connection."
+msgstr ""
+"En hændelse opstod under forsøget på at indsende et rettesæt. Hvis det sker "
+"gentagne gange, overvej da at rapportere en fejl via menuen Hjælp. Hvis "
+"denne meddelelse vises for første gang, så prøv igen. Der kan have været et "
+"problem med internetforbindelsen."
+
+msgid "Cancel"
+msgstr "Annuller"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr "Rettesæt upload mislykkedes med {0} fejl ''{1} {2}''!"
+
+msgid "Choose signs"
+msgstr "Vælg skilte"
+
+msgid "Continues with the paused walk."
+msgstr "Fortsætter med den gåtur der er på pause."
+
+msgid "Copy key"
+msgstr "Kopier nøgle"
+
+msgid "Could not import a geotagged image to the Mapillary layer!"
+msgstr "Kunne ikke importere et geotagget billede til Mapillary laget!"
+
+#, java-format
+msgid "Could not import the directory ''{0}''!"
+msgstr "Kunne ikke importere mappen ''{0}''!"
+
+#, java-format
+msgid "Could not import the image ''{0}''!"
+msgstr "Kunne ikke importere billedet ''{0}''!"
+
+#, java-format
+msgid "Could not open the URL {0} in a browser"
+msgstr "Kunne ikke åbne URL {0} i en browser"
+
+#, java-format
+msgid "Could not read from URL {0}!"
+msgstr "Kunne ikke læse fra URL {0}!"
+
+msgid "Current Mapillary changeset"
+msgstr "Aktuelt Mapillary rettesæt"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Cut off sequences at download bounds"
+msgstr "Afskær sekvenser ved download grænse"
+
+msgid "Days"
+msgstr "Dage"
+
+msgid "Delete after upload"
+msgstr "Slet efter upload"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "Slettede {0} billede"
+msgstr[1] "Slettede {0} billeder"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Vis hvornår billedet blev taget"
+
+msgid "Displays detail information on the currently selected Mapillary image"
+msgstr "Viser detaljerede oplysninger om det aktuelt valgte Mapillary billede"
+
+msgid "Displays objects detected by Mapillary from their street view imagery"
+msgstr ""
+"Viser objekter der er registreret af Mapillary fra deres gade niveau "
+"billeder"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr "Viser laget der viser de kortobjekter, der er fundet af Mapillary"
+
+#, java-format
+msgid ""
+"Do you really want to replace the current value <i>{0}</i> with the new "
+"value <i>{1}</i>?"
+msgstr ""
+"Vil du virkelig erstatte den nuværende værdi <i>{0}</i> med den nye værdi "
+"<i>{1}</i>?"
+
+msgid "Download Mapillary images in current view"
+msgstr "Download Mapillary billeder i den aktuelle visning"
+
+msgid "Download mode"
+msgstr "Download tilstand"
+
+msgid "Downloaded images"
+msgstr "Downloadede billeder"
+
+msgid "Downloading"
+msgstr "Downloader"
+
+msgid "Downloading Mapillary images"
+msgstr "Downloader Mapillary billeder"
+
+msgid "Downloading map objects failed!"
+msgstr "Downloading af kortobjekter mislykkedes!"
+
+msgid "Downloading map objects…"
+msgstr "Downloader kortobjekter…"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr "Aktiver eksperimentelle beta-funktioner (muligvis ustabil)"
+
+msgid "Explore"
+msgstr "Filstyringsprogram"
+
+msgid "Export Mapillary images"
+msgstr "Exporter Mapillary billeder"
+
+msgid "Export all images"
+msgstr "Eksporter alle billeder"
+
+msgid "Export selected images"
+msgstr "Eksporter valgte billeder"
+
+msgid "Export selected sequence"
+msgstr "Eksporter valgte rækkefølge"
+
+msgid "Exporting Mapillary Images"
+msgstr "Eksporter Mapillary billeder"
+
+msgid "Finished upload"
+msgstr "Upload færdig"
+
+msgid "Follow selected image"
+msgstr "Følg valgt billede"
+
+msgid "From existing image layer"
+msgstr "Fra eksisterende billedlag"
+
+msgid "From which source do you want to import images to the Mapillary layer?"
+msgstr "Fra hvilken kilde vil du importere billeder til Mapillary laget?"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Ubetinget vigepligt"
+
+msgid "Go forward"
+msgstr "Gå frem"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr "Gå til indstilling og log på Mapillary før upload."
+
+msgid "I got it, close this."
+msgstr "Jeg fik det, luk dette."
+
+msgid "Image actions"
+msgstr "Billedhandlinger"
+
+msgid "Image detections"
+msgstr "Billedetektioner"
+
+msgid "Image info"
+msgstr "Billedinformation"
+
+msgid "Image key"
+msgstr "Billednøgle"
+
+msgid "Images from my file system"
+msgstr "Billeder fra mit filsystem"
+
+msgid "Import"
+msgstr "Importer"
+
+msgid "Import exception"
+msgstr "Import hændelse"
+
+msgid "Import local pictures"
+msgstr "Importer lokale billeder"
+
+msgid "Import pictures"
+msgstr "Importer billeder"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Importer billeder til Mapillary lag"
+
+msgid "Imported images"
+msgstr "Importerede billeder"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "Importerede {0} billede"
+msgstr[1] "Importerede {0} billeder"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Farligt vejkryds"
+
+msgid ""
+"It can be activated by clicking the left button at the bottom of this "
+"message or the button in the toolbar on the left, which uses the same icon."
+msgstr ""
+"Det kan aktiveres ved at klikke på den venstre knap nederst i denne "
+"meddelelse eller knappen i værktøjslinjen til venstre, som bruger det samme "
+"ikon."
+
+msgid "Join mode"
+msgstr "Sammenlæg tilstand"
+
+msgid "Join/unjoin pictures"
+msgstr "Sammenlæg/adskil billeder"
+
+msgid "Jump to blue"
+msgstr "Hop til blå"
+
+msgid "Jump to red"
+msgstr "Hop til rød"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Hopper til billedet i den anden ende af den blå linje"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Hopper til billedet i den anden ende af den røde linje"
+
+msgid "Key copied to clipboard"
+msgstr "Nøgle kopieret til udklipsholder"
+
+msgid "Login"
+msgstr "Log ind"
+
+msgid "Login successful, return to JOSM."
+msgstr "Login lykkes, vend tilbage til JOSM."
+
+msgid "Logout"
+msgstr "Log ud"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Påbudt kørselsretning (enhver)"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Mapillary billeder"
+
+msgid "Mapillary changeset"
+msgstr "Mapillary rettesæt"
+
+msgid "Mapillary filter"
+msgstr "Mapillary filter"
+
+msgid "Mapillary history"
+msgstr "Mapillary historie"
+
+msgid "Mapillary image"
+msgstr "Mapillary billede"
+
+msgid "Mapillary layer"
+msgstr "Mapillary lag"
+
+msgid "Mapillary login"
+msgstr "Mapillary login"
+
+msgid "Display Mapillary objects"
+msgstr "Mapillary objekt lag"
+
+msgid "Mapillary objects"
+msgstr "Mapillary objekter"
+
+msgid "Months"
+msgstr "Måneder"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr "Flyt til billedets placering med næste/forrige knapper"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "Flyttede {0} billede"
+msgstr[1] "Flyttede {0} billeder"
+
+msgid "Next picture"
+msgstr "Næste billede"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "Indkørsel forbudt"
+
+msgid "No image selected"
+msgstr "Intet billede valgt"
+
+msgid "No images found"
+msgstr "Ingen billeder fundet"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "Overhaling forbudt"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "Parking forbudt"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "Sving forbudt"
+
+msgid "Not Logged in to Mapillary"
+msgstr "Ikke logget ind på Mapillary"
+
+msgid "Not older than: "
+msgstr "Ikke ældre end: "
+
+#. i18n: Spinner label in JOSM settings
+msgid "Number of images to be pre-fetched (forwards and backwards)"
+msgstr "Antal billeder der skal hentes (frem og tilbage)"
+
+msgid "Only images with signs"
+msgstr "Kun billeder med skilte"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Åben Mapillary rettesæt dialog"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Åbn Mapillary dialog filter"
+
+msgid "Open Mapillary history dialog"
+msgstr "Åbn Mapillary historie dialog"
+
+msgid "Open Mapillary layer"
+msgstr "Åben Mapillary lag"
+
+msgid "Open Mapillary window"
+msgstr "Åbn Mapillary vindue"
+
+msgid "Pause"
+msgstr "Pause"
+
+msgid "Pauses the walk."
+msgstr "Sætter gåturen på pause."
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Fodgængerfelt"
+
+msgid "Play"
+msgstr "Afspil"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "Tryk \"{0}\" for at downloade billeder"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Forhåndsvis billeder når markør er over dets ikon"
+
+msgid "Previous picture"
+msgstr "Forrige billede"
+
+msgid "Redo"
+msgstr "Gendan"
+
+msgid "Reset"
+msgstr "Nulstil"
+
+msgid "Rewrite imported images"
+msgstr "Genskriv importerede billeder"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Rundkørsel"
+
+msgid "Select a directory"
+msgstr "Vælg en mappe"
+
+msgid "Select directory to import images from"
+msgstr "Vælg mappe til at importere billeder fra"
+
+msgid "Select mode"
+msgstr "Vælg tilstand"
+
+msgid "Select the images you want to import"
+msgstr "Vælg de billeder du vil importere"
+
+msgid "Sequence key"
+msgstr "Sekvensnøgle"
+
+msgid "Show detections on top of image"
+msgstr "Vis detekteringer oven på billedet"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Viser det næste billede i sekvensen"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Viser det forrige billede i sekvensen"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Hastighedsbegrænsning"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Stop"
+
+msgid "Stops the walk."
+msgstr "Stopper gåtur."
+
+msgid "Submit changeset"
+msgstr "Indsend rettesæt"
+
+msgid "Submit the current changeset"
+msgstr "Indsend det aktuelle rettesæt"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "Indsend det aktuelle rettesæt til Mapillary"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "Indsender Mapillary rettesæt"
+
+msgid "Submitting changeset to server…"
+msgstr "Indsender rettesæt til server…"
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Understøttede billedformater (JPG og PNG)"
+
+msgid "Tag conflict"
+msgstr "Tag konflikt"
+
+msgid ""
+"The Mapillary layer has stopped downloading images, because the requested "
+"area is too big!"
+msgstr ""
+"Mapillary laget er stoppet med at downloade billeder, fordi det ønskede "
+"område er for stort!"
+
+msgid ""
+"The Mapillary plugin now uses a separate panel to display extra information "
+"(like the image key) and actions for the currently selected Mapillary image "
+"(like viewing it in a browser)."
+msgstr ""
+"Mapillary udvidelsen bruger nu et separat panel til at vise ekstra "
+"information (som billednøglen) og handlinger for det aktuelt valgte "
+"Mapillary billede (som at se det i en browser)."
+
+msgid "There are currently no layers with geotagged images!"
+msgstr "Der er i øjeblikket ingen lag med geotagged billeder!"
+
+#, java-format
+msgid ""
+"To solve this problem, you could switch to download mode ''{0}'' and load "
+"Mapillary images for a smaller portion of the map."
+msgstr ""
+"For at løse dette problem kan du skifte til download mode ''{0}'' og indlæse"
+" Mapillary billeder for en mindre del af kortet."
+
+msgid ""
+"To solve this problem, you could zoom in and load a smaller area of the map."
+msgstr ""
+"For at løse dette problem kan du zoome ind og indlæse et mindre område på "
+"kortet."
+
+msgid "Too many map objects, zoom in to see all."
+msgstr "For mange kortobjekter, zoom ind for at se alle."
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Total antal Mapillary billeder: {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "Drejede {0} billede"
+msgstr[1] "Drejede {0} billeder"
+
+msgid "Undo"
+msgstr "Fortryd"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Ujævn vej"
+
+msgid "Update"
+msgstr "Opdater"
+
+msgid "Upload selected sequence"
+msgstr "Upload valgt rækkefølge"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Uploader: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "Brug 24-timers format"
+
+msgid "User"
+msgstr "Bruger"
+
+msgid "View in browser"
+msgstr "Vis i browser"
+
+msgid "Wait for full quality pictures"
+msgstr "Vent på fuld kvalitets billeder"
+
+msgid "Walk mode"
+msgstr "Gå tilstand"
+
+#. i18n: Checkbox label in JOSM settings
+msgid ""
+"When opening Mapillary image in web browser, show the blur editor instead of"
+" the image viewer"
+msgstr ""
+"Ved åbning af Mapillary billede i webbrowser, vis sløringseditoren i stedet "
+"for billedviseren"
+
+msgid "Which image layers do you want to import into the Mapillary layer?"
+msgstr "Hvilke billedlag vil du importere til Mapillary laget?"
+
+msgid "Years"
+msgstr "År"
+
+msgid "You are currently not logged in."
+msgstr "Du er i øjeblikket ikke logget ind."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "Du er logget ind som ''{0}''."
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr ""
+"Du er ikke logget ind, du kan logge ind på Mapillary under indstillinger"
+
+#, java-format
+msgid "You have successfully uploaded {0} images to mapillary.com"
+msgstr "Du har med succes uploadet {0} billeder til mapillary.com"
+
+msgid "Zoom to selected image"
+msgstr "Zoom til valgt billede"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Zoom til det aktuelt valgt Mapillary billede"
+
+msgid "approved"
+msgstr "godkendt"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "områder med downloadet OSM-data"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "alt i det synlige område"
+
+msgid "image has no key"
+msgstr "Billedet har ingen nøgle"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "kun ved manuel anmodet"
+
+msgid "pending"
+msgstr "afventer"
+
+msgid "rejected"
+msgstr "afvist"
+
+msgid "sequence has no key"
+msgstr "sekvens har ingen nøgle"
+
+msgid "unknown user"
+msgstr "ukendt bruger"
+
+#, java-format
+msgid ""
+"{0}\n"
+"Could not read map objects from URL\n"
+"{1}!"
+msgstr ""
+"{0}\n"
+"Kunne ikke læse kortobjekter fra URL\n"
+"{1}!"
+
+#. i18n: {0} is the layer name, {1} the number of images in it
+#, java-format
+msgid "{0} ({1} images)"
+msgstr "{0} ({1} billeder)"
+
+#, java-format
+msgid "{0} detections"
+msgstr "{0} detekteringer"
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "{0} downloadede billeder"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "{0} billeder i alt"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{0} billeder i {1} sekvenser"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr "{0} indsendte billeder, Rettesæt nøgle: {1}, Tilstand: {2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "{0} importerede billeder"
+
+#, java-format
+msgid "{0} sequences, each containing between {1} and {2} images (ø {3})"
+msgstr "{0} sekvenser, der hver indeholder mellem {1} og {2} billeder (ø {3})"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr "Tillader brugeren at arbejde med billeder gemt på mapillary.com"
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/de.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/de.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/de.po	(revision 34317)
@@ -0,0 +1,678 @@
+# Translations for the JOSM plugin 'Mapillary' (de)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: malenki <transifex@malenki.ch>, 2018\n"
+"Language-Team: German (https://www.transifex.com/josm/teams/2544/de/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: de\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgid "2 images joined"
+msgstr "2 Bilder verbunden"
+
+msgid "2 images unjoined"
+msgstr "2 Bilder getrennt"
+
+#, java-format
+msgid ""
+"A tag with key <i>{0}</i> is already present on the selected OSM object."
+msgstr ""
+"Ein Tag mit dem Schlüssel <i>{0}</i> ist bereits bei dem ausgewählten OSM-"
+"Objekt vorhanden."
+
+msgid "Add Mapillary tag"
+msgstr "Mapillary-Tag hinzufügen"
+
+msgid "All images in a directory"
+msgstr "Alle Bilder in einem Verzeichnis"
+
+msgid "All map objects loaded."
+msgstr "Alle Kartenobjekte geladen."
+
+msgid ""
+"An exception occured while trying to submit a changeset. If this happens "
+"repeatedly, consider reporting a bug via the Help menu. If this message "
+"appears for the first time, simply try it again. This might have been an "
+"issue with the internet connection."
+msgstr ""
+"Bei der Übertragung eines Änderungssatzes ist ein Fehler aufgetreten. Falls "
+"dies wiederholt auftritt, sollte der Fehler mittels des Hilfe-Menüs gemeldet"
+" werden. Wenn diese Nachricht zum ersten Mal erscheint, versuche es einfach "
+"noch einmal. Es könnte sich um ein Problem mit der Internetverbindung "
+"gehandelt haben."
+
+msgid "Cancel"
+msgstr "Abbrechen"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr "Hochladen des Änderungssatzes fehlgeschlagen mit {0} Fehler \"{1} {2}\"!"
+
+msgid "Choose signs"
+msgstr "Verkehrszeichen auswählen"
+
+msgid "Continues with the paused walk."
+msgstr "Setzt den pausierten Spaziergang fort."
+
+msgid "Copy key"
+msgstr "Schlüssel kopieren"
+
+msgid "Could not import a geotagged image to the Mapillary layer!"
+msgstr ""
+"Konnte ein georeferenziertes Bild nicht in die Mapillary-Ebene importieren!"
+
+#, java-format
+msgid "Could not import the directory ''{0}''!"
+msgstr "Verzeichnis ''{0}'' konnte nicht importiert werden!"
+
+#, java-format
+msgid "Could not import the image ''{0}''!"
+msgstr "Bild ''{0}'' konnte nicht importiert werden!"
+
+#, java-format
+msgid "Could not open the URL {0} in a browser"
+msgstr "Konnte die URL {0} nicht in einem Browser öffnen"
+
+#, java-format
+msgid "Could not read from URL {0}!"
+msgstr "Konnte nicht von URL {0} lesen!"
+
+msgid "Current Mapillary changeset"
+msgstr "Aktueller Mapillary-Änderungssatz"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Cut off sequences at download bounds"
+msgstr "Schneide Sequenzen an den Herunterladegrenzen ab"
+
+msgid "Days"
+msgstr "Tage"
+
+msgid "Delete after upload"
+msgstr "Nach dem Hochladen löschen"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "{0} Bild gelöscht"
+msgstr[1] "{0} Bilder gelöscht"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Stunde, in der das Bild gemacht wurde, anzeigen"
+
+msgid "Displays detail information on the currently selected Mapillary image"
+msgstr ""
+"Angeige von detaillierten Informationen über das momentan ausgewählte "
+"Mapillary-Bild"
+
+msgid "Displays objects detected by Mapillary from their street view imagery"
+msgstr "Zeigt von Mapillary erkannte Objekte der Straßenansichtsbilder an"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr ""
+"Zeigt die Ebene an, welche von Mapillary erkannte Kartenobjekte darstellt"
+
+#, java-format
+msgid ""
+"Do you really want to replace the current value <i>{0}</i> with the new "
+"value <i>{1}</i>?"
+msgstr ""
+"Möchten Sie wirklich den jetzigen Wert <i>{0}</i> mit dem neuen Wert "
+"<i>{1}</i> ersetzen?"
+
+msgid "Download Mapillary images in current view"
+msgstr "Mapillary-Bilder in aktueller Ansicht herunterladen"
+
+msgid "Download mode"
+msgstr "Herunterlademodus"
+
+msgid "Downloaded images"
+msgstr "Heruntergeladene Bilder"
+
+msgid "Downloading"
+msgstr "Wird heruntergeladen"
+
+msgid "Downloading Mapillary images"
+msgstr "Mapillary-Bilder werden heruntergeladen"
+
+msgid "Downloading map objects failed!"
+msgstr "Herunterladen von Kartenobjekten fehlgeschlagen!"
+
+msgid "Downloading map objects…"
+msgstr "Kartenobjekte werden heruntergeladen…"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr "Experimentelle Beta-Funktionalität aktivieren (kann instabil sein)"
+
+msgid "Explore"
+msgstr "Erkunden"
+
+msgid "Export Mapillary images"
+msgstr "Mapillary-Bilder exportieren"
+
+msgid "Export all images"
+msgstr "Alle Bilder exportieren"
+
+msgid "Export selected images"
+msgstr "Ausgewählte Bilder exportieren"
+
+msgid "Export selected sequence"
+msgstr "Ausgewählte Sequenz exportieren"
+
+msgid "Exporting Mapillary Images"
+msgstr "Exportiere Mapillary-Bilder"
+
+msgid "Finished upload"
+msgstr "Hochladen abgeschlossen"
+
+msgid "Follow selected image"
+msgstr "Ausgewähltem Bild folgen"
+
+msgid "From existing image layer"
+msgstr "Von vorhandener Bildebene"
+
+msgid "From which source do you want to import images to the Mapillary layer?"
+msgstr ""
+"Von welcher Quelle möchten Sie Bilder auf die Mapillary-Ebene importieren?"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Vorfahrt gewähren"
+
+msgid "Go forward"
+msgstr "Vorwärts gehen"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr ""
+"Gehen Sie in die Einstellung und melden Sie sich vor dem Hochladen bei "
+"Mapillary an."
+
+msgid "I got it, close this."
+msgstr "Ich habe verstanden, Nachricht schließen."
+
+msgid "Image actions"
+msgstr "Bildaktionen"
+
+msgid "Image detections"
+msgstr "Bilderkennungen"
+
+msgid "Image info"
+msgstr "Bildinformationen"
+
+msgid "Image key"
+msgstr "Bildschlüssel"
+
+msgid "Images from my file system"
+msgstr "Bilder von meinem Dateisystem"
+
+msgid "Import"
+msgstr "Importieren"
+
+msgid "Import exception"
+msgstr "Importausnahme"
+
+msgid "Import local pictures"
+msgstr "Lokale Bilder importieren"
+
+msgid "Import pictures"
+msgstr "Bilder importieren"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Bilder in Mapillary-Ebene importieren"
+
+msgid "Imported images"
+msgstr "Importierte Bilder"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "{0} Bild importiert"
+msgstr[1] "{0} Bilder importiert"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Gefährliche Kreuzung"
+
+msgid ""
+"It can be activated by clicking the left button at the bottom of this "
+"message or the button in the toolbar on the left, which uses the same icon."
+msgstr ""
+"Es kann durch klicken auf den Knopf links unten in dieser Nachricht oder auf"
+" den Knopf mit dem selben Symbol in der Werkzeugleiste am linken Rand des "
+"JOSM-Fensters aktiviert werden."
+
+msgid "Join mode"
+msgstr "Verbindungsmodus"
+
+msgid "Join/unjoin pictures"
+msgstr "Bilder verbinden/trennen"
+
+msgid "Jump to blue"
+msgstr "Zu Blau wechseln"
+
+msgid "Jump to red"
+msgstr "Zu Rot wechseln"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Wechselt zu dem Bild auf der anderen Seite der blauen Linie"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Wechselt zu dem Bild auf der anderen Seite der roten Linie"
+
+msgid "Key copied to clipboard"
+msgstr "Schlüssel wurde in die Zwischenablage kopiert"
+
+msgid "Login"
+msgstr "Anmelden"
+
+msgid "Login successful, return to JOSM."
+msgstr "Anmeldung erfolgreich, zurück zu JOSM."
+
+msgid "Logout"
+msgstr "Abmelden"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Vorgeschriebene Richtung (beliebig)"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Mapillary-Bilder"
+
+msgid "Mapillary changeset"
+msgstr "Mapillary-Änderungssatz"
+
+msgid "Mapillary filter"
+msgstr "Mapillary-Filter"
+
+msgid "Mapillary history"
+msgstr "Mapillary-Chronik"
+
+msgid "Mapillary image"
+msgstr "Mapillary-Bild"
+
+msgid "Mapillary layer"
+msgstr "Mapillary-Ebene"
+
+msgid "Mapillary login"
+msgstr "Mapillary-Anmeldung"
+
+msgid "Mapillary object layer"
+msgstr "Mapillary-Objektebene"
+
+msgid "Mapillary objects"
+msgstr "Mapillary-Objekte"
+
+msgid "Months"
+msgstr "Monate"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr ""
+"Wechseln Sie zur Bildadresse mit den nächstes/vorheriges Schaltflächen"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "{0} Bild verschoben"
+msgstr[1] "{0} Bilder verschoben"
+
+msgid "Next picture"
+msgstr "Nächstes Bild"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "Einfahrt verboten"
+
+msgid "No image selected"
+msgstr "Kein Bild ausgewählt"
+
+msgid "No images found"
+msgstr "Keine Bilder gefunden"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "Überholverbot"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "Parkverbot"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "Abbiegen verboten"
+
+msgid "Not Logged in to Mapillary"
+msgstr "Nicht bei Mapillary angemeldet"
+
+msgid "Not older than: "
+msgstr "Nicht älter als: "
+
+#. i18n: Spinner label in JOSM settings
+msgid "Number of images to be pre-fetched (forwards and backwards)"
+msgstr "Anzahl der vorab abzurufenden Bilder (vorwärts und rückwärts)"
+
+msgid "Only images with signs"
+msgstr "Nur Bilder mit Verkehrszeichen"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Mapillary-Änderungssatzdialog öffnen"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Mapillary-Filterdialog öffnen"
+
+msgid "Open Mapillary history dialog"
+msgstr "Mapillary-Chronikdialog öffnen"
+
+msgid "Open Mapillary layer"
+msgstr "Mapillary-Ebene öffnen"
+
+msgid "Open Mapillary window"
+msgstr "Mapillary Fenster öffnen"
+
+msgid "Pause"
+msgstr "Pause"
+
+msgid "Pauses the walk."
+msgstr "Pausiert den Spaziergang."
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Fußgängerübergang"
+
+msgid "Play"
+msgstr "Wiedergabe"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "Zum Herunterladen von Bildern \"{0}\" drücken"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Beim Überfahren des Symbols Vorschaubilder anzeigen"
+
+msgid "Previous picture"
+msgstr "Vorheriges Bild"
+
+msgid "Redo"
+msgstr "Wiederherstellen"
+
+msgid "Reset"
+msgstr "Zurücksetzen"
+
+msgid "Rewrite imported images"
+msgstr "Importierte Bilder neu schreiben"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Kreisverkehr"
+
+msgid "Select a directory"
+msgstr "Wählen Sie ein Verzeichnis aus"
+
+msgid "Select directory to import images from"
+msgstr "Wählen Sie das Verzeichnis zum Importieren von Bildern aus"
+
+msgid "Select mode"
+msgstr "Auswahlmodus"
+
+msgid "Select the images you want to import"
+msgstr "Wählen Sie die Bilder aus, die Sie importieren möchten"
+
+msgid "Sequence key"
+msgstr "Sequenzschlüssel"
+
+msgid "Show detections on top of image"
+msgstr "Zeige Erkennungen über dem Bild"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Zeigt das nächste Bild in der Sequenz an"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Zeigt das vorherige Bild in der Sequenz an"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Geschwindigkeitsbegrenzung"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Stopp-Schild"
+
+msgid "Stops the walk."
+msgstr "Stoppt den Spaziergang."
+
+msgid "Submit changeset"
+msgstr "Änderungssatz absenden"
+
+msgid "Submit the current changeset"
+msgstr "Aktuellen Änderungssatz absenden"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "Aktuellen Änderungssatz zu Mapillary absenden"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "Mapillary-Änderungssatz wird gesendet"
+
+msgid "Submitting changeset to server…"
+msgstr "Änderungssatz wird an Server gesendet…"
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Unterstützte Bildformate (JPG und PNG)"
+
+msgid "Tag conflict"
+msgstr "Tag-Konflikt"
+
+msgid ""
+"The Mapillary layer has stopped downloading images, because the requested "
+"area is too big!"
+msgstr ""
+"Die Mapillary-Ebene hat das Herunterladen von Bildern gestoppt, weil der "
+"angeforderte Bereich zu groß ist!"
+
+msgid ""
+"The Mapillary plugin now uses a separate panel to display extra information "
+"(like the image key) and actions for the currently selected Mapillary image "
+"(like viewing it in a browser)."
+msgstr ""
+"Das Mapillary-Plugin verwendet nun ein separates Fenster, um zusätzliche "
+"Informationen (z.B. den Schlüssel des Bildes) sowie Aktionen für das "
+"momentan ausgewählte Bild (z.B. das Bild in einem Browser anzuzeigen) "
+"anzuzeigen."
+
+msgid "There are currently no layers with geotagged images!"
+msgstr "There are currently no layers with geotagged images!"
+
+#, java-format
+msgid ""
+"To solve this problem, you could switch to download mode ''{0}'' and load "
+"Mapillary images for a smaller portion of the map."
+msgstr ""
+"Um dieses Problem zu lösen, können Sie in den Herunterlademodus ''{0}'' "
+"wechseln und Mapillary-Bilder für einen kleineren Teil der Karte laden."
+
+msgid ""
+"To solve this problem, you could zoom in and load a smaller area of the map."
+msgstr ""
+"Um dieses Problem zu lösen, können Sie einen kleineren Ausschnitt der Karte "
+"vergrößern und laden."
+
+msgid "Too many map objects, zoom in to see all."
+msgstr "Zu viele Kartenobjekte, vergrößern um alle zu sehen."
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Mapillary-Bilder insgesamt: {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "{0} Bild gedreht"
+msgstr[1] "{0} Bilder gedreht"
+
+msgid "Undo"
+msgstr "Rückgängig"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Unebene Fahrbahn"
+
+msgid "Update"
+msgstr "Aktualisieren"
+
+msgid "Upload selected sequence"
+msgstr "Ausgewählte Sequenz hochladen"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Hachladevorgang: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "24-Stunden-Format verwenden"
+
+msgid "User"
+msgstr "Nutzer"
+
+msgid "View in browser"
+msgstr "Im Webbrowser ansehen"
+
+msgid "Wait for full quality pictures"
+msgstr "Warten Sie für Bilder in voller Qualität"
+
+msgid "Walk mode"
+msgstr "Spaziergangmodus"
+
+#. i18n: Checkbox label in JOSM settings
+msgid ""
+"When opening Mapillary image in web browser, show the blur editor instead of"
+" the image viewer"
+msgstr ""
+"Beim Öffnen eines Mapillary Bildes im Webbrowser den Unschärfe-Editor "
+"anstelle des Bildbetrachters anzeigen"
+
+msgid "Which image layers do you want to import into the Mapillary layer?"
+msgstr "Welche Bildebenen möchten Sie in die Mapillary-Ebene importieren?"
+
+msgid "Years"
+msgstr "Jahre"
+
+msgid "You are currently not logged in."
+msgstr "Sie sind momentan nicht angemeldet."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "Sie sind als ''{0}'' angemeldet."
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr ""
+"Sie sind nicht angemeldet, bitte melden Sie sich in den Einstellungen bei "
+"Mapillary an"
+
+#, java-format
+msgid "You have successfully uploaded {0} images to mapillary.com"
+msgstr "Sie haben {0} Bilder erfolgreich zu mapillary.com hochgeladen"
+
+msgid "Zoom to selected image"
+msgstr "Auf ausgewähltes Bild zoomen"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Auf das aktuell ausgewählte Mapillary-Bild zoomen"
+
+msgid "approved"
+msgstr "genehmigt"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "Gebiete mit heruntergeladenen OSM-Daten"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "alles im sichtbaren Bereich"
+
+msgid "image has no key"
+msgstr "Bild hat keinen Schlüssel"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "nur wenn manuell angefordert"
+
+msgid "pending"
+msgstr "ausstehend"
+
+msgid "rejected"
+msgstr "abgelehnt"
+
+msgid "sequence has no key"
+msgstr "Sequenz hat keinen Schlüssel"
+
+msgid "unknown user"
+msgstr "unbekannter Nutzer"
+
+#, java-format
+msgid ""
+"{0}\n"
+"Could not read map objects from URL\n"
+"{1}!"
+msgstr ""
+"{0}\n"
+"Kartenobjekte konnten nicht von URL\n"
+"{1}\n"
+"gelesen werden!"
+
+#. i18n: {0} is the layer name, {1} the number of images in it
+#, java-format
+msgid "{0} ({1} images)"
+msgstr "{0} ({1} Bilder)"
+
+#, java-format
+msgid "{0} detections"
+msgstr "{0} Erkennungen"
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "{0} heruntergeladene Bilder"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "{0} Bilder insgesamt"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{0} Bilder in {1} Sequenzen"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr "{0} Bilder eingereicht, Änderungssatzschlüssel: {1}, Status: {2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "{0} importierte Bilder"
+
+#, java-format
+msgid "{0} sequences, each containing between {1} and {2} images (ø {3})"
+msgstr "{0} Sequenzen, jede enthält zwischen {1} und {2} Bilder (ø {3})"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr ""
+"Ermöglicht dem Benutzer das Arbeiten mit von mapillary.com bereitgestellten "
+"Bildern"
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/en_GB.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/en_GB.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/en_GB.po	(revision 34317)
@@ -0,0 +1,449 @@
+# Translations for the JOSM plugin 'MS-Streetside-JOSM-Plugin' (en_GB)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: floscher, 2018\n"
+"Language-Team: English (United Kingdom) (https://www.transifex.com/josm/teams/2544/en_GB/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: en_GB\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgid "2 images joined"
+msgstr "2 images joined"
+
+msgid "2 images unjoined"
+msgstr "2 images unjoined"
+
+msgid "Cancel"
+msgstr "Cancel"
+
+msgid "Choose signs"
+msgstr "Choose signs"
+
+msgid "Continues with the paused walk."
+msgstr "Continues with the paused walk."
+
+msgid "Current Mapillary changeset"
+msgstr "Current Mapillary changeset"
+
+msgid "Current Streetside changeset"
+msgstr "Current Streetside changeset"
+
+msgid "Days"
+msgstr "Days"
+
+msgid "Delete after upload"
+msgstr "Delete after upload"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "Deleted {0} image"
+msgstr[1] "Deleted {0} images"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Display hour when the picture was taken"
+
+msgid "Download Mapillary images in current view"
+msgstr "Download Mapillary images in current view"
+
+msgid "Download mode"
+msgstr "Download mode"
+
+msgid "Downloaded images"
+msgstr "Downloaded images"
+
+msgid "Downloading"
+msgstr "Downloading"
+
+msgid "Downloading Mapillary images"
+msgstr "Downloading Mapillary images"
+
+msgid "Downloading Streetside images"
+msgstr "Downloading Streetside images"
+
+msgid "Explore"
+msgstr "Explore"
+
+msgid "Export all images"
+msgstr "Export all images"
+
+msgid "Export selected images"
+msgstr "Export selected images"
+
+msgid "Export selected sequence"
+msgstr "Export selected sequence"
+
+msgid "Finished upload"
+msgstr "Finished upload"
+
+msgid "Follow selected image"
+msgstr "Follow selected image"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Give way"
+
+msgid "Go forward"
+msgstr "Go forward"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr "Go to setting and log in to Mapillary before uploading."
+
+msgid "Go to setting and log in to Streetside before uploading."
+msgstr "Go to setting and log in to Streetside before uploading."
+
+msgid "Import"
+msgstr "Import"
+
+msgid "Import local pictures"
+msgstr "Import local pictures"
+
+msgid "Import pictures"
+msgstr "Import pictures"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Import pictures into Mapillary layer"
+
+msgid "Imported images"
+msgstr "Imported images"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "Imported {0} image"
+msgstr[1] "Imported {0} images"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Intersection danger"
+
+msgid "Join mode"
+msgstr "Join mode"
+
+msgid "Join/unjoin pictures"
+msgstr "Join/unjoin pictures"
+
+msgid "Jump to blue"
+msgstr "Jump to blue"
+
+msgid "Jump to red"
+msgstr "Jump to red"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Jumps to the picture at the other side of the blue line"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Jumps to the picture at the other side of the red line"
+
+msgid "Login"
+msgstr "Login"
+
+msgid "Login successful, return to JOSM."
+msgstr "Login successful, return to JOSM."
+
+msgid "Logout"
+msgstr "Logout"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Mandatory direction (any)"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Mapillary Images"
+
+msgid "Microsoft Streetside Images"
+msgstr "Microsoft Streetside Images"
+
+msgid "Mapillary changeset"
+msgstr "Mapillary changeset"
+
+msgid "Streetside changeset"
+msgstr "Streetside changeset"
+
+msgid "Mapillary filter"
+msgstr "Mapillary filter"
+
+msgid "Streetside filter"
+msgstr "Streetside filter"
+
+msgid "Mapillary history"
+msgstr "Mapillary history"
+
+msgid "Streetside history"
+msgstr "Streetside history"
+
+msgid "Mapillary layer"
+msgstr "Mapillary layer"
+
+msgid "Streetside layer"
+msgstr "Streetside layer"
+
+msgid "Mapillary login"
+msgstr "Mapillary login"
+
+msgid "Streetside login"
+msgstr "Streetside login"
+
+msgid "Months"
+msgstr "Months"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr "Move to picture''s location with next/previous buttons"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "Moved {0} image"
+msgstr[1] "Moved {0} images"
+
+msgid "Next picture"
+msgstr "Next picture"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "No entry"
+
+msgid "No image selected"
+msgstr "No image selected"
+
+msgid "No images found"
+msgstr "No images found"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "No overtaking"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "No parking"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "No turn"
+
+msgid "Not Logged in to Mapillary"
+msgstr "Not Logged in to Mapillary"
+
+msgid "Not Logged in to Streetside"
+msgstr "Not Logged in to Streetside"
+
+msgid "Not older than: "
+msgstr "Not older than: "
+
+msgid "Only images with signs"
+msgstr "Only images with signs"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Open Mapillary changeset dialogue"
+
+msgid "Open Streetside changeset dialog"
+msgstr "Open Streetside changeset dialogue"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Open Mapillary filter dialog"
+
+msgid "Open Streetside filter dialog"
+msgstr "Open Streetside filter dialog"
+
+msgid "Open Mapillary history dialog"
+msgstr "Open Mapillary history dialog"
+
+msgid "Open Streetside history dialog"
+msgstr "Open Streetside history dialog"
+
+msgid "Open Mapillary window"
+msgstr "Open Mapillary window"
+
+msgid "Open Streetside window"
+msgstr "Open Streetside window"
+
+msgid "Pause"
+msgstr "Pause"
+
+msgid "Pauses the walk."
+msgstr "Pauses the walk."
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Pedestrian crossing"
+
+msgid "Play"
+msgstr "Play"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Preview images when hovering its icon"
+
+msgid "Previous picture"
+msgstr "Previous picture"
+
+msgid "Redo"
+msgstr "Redo"
+
+msgid "Reset"
+msgstr "Reset"
+
+msgid "Rewrite imported images"
+msgstr "Rewrite imported images"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Roundabout"
+
+msgid "Select a directory"
+msgstr "Select a directory"
+
+msgid "Select mode"
+msgstr "Select mode"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Shows the next picture in the sequence"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Shows the previous picture in the sequence"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Speed limit"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Stop"
+
+msgid "Stops the walk."
+msgstr "Stops the walk."
+
+msgid "Submit changeset"
+msgstr "Submit changeset"
+
+msgid "Submit the current changeset"
+msgstr "Submit the current changeset"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "Submit the current changeset to Mapillary"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Streetside"
+msgstr "Submit the current changeset to Streetside"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "Submitting Mapillary Changeset"
+
+msgid "Submitting Streetside Changeset"
+msgstr "Submitting Streetside Changeset"
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Supported image formats (JPG and PNG)"
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Total Mapillary images: {0}"
+
+#, java-format
+msgid "Total Streetside images: {0}"
+msgstr "Total Streetside images: {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "Turned {0} image"
+msgstr[1] "Turned {0} images"
+
+msgid "Undo"
+msgstr "Undo"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Uneven road"
+
+msgid "Update"
+msgstr "Update"
+
+msgid "Upload selected sequence"
+msgstr "Upload selected sequence"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Uploading: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "Use 24 hour format"
+
+msgid "User"
+msgstr "User"
+
+msgid "Wait for full quality pictures"
+msgstr "Wait for full quality pictures"
+
+msgid "Walk mode"
+msgstr "Walk mode"
+
+msgid "Years"
+msgstr "Years"
+
+msgid "You are currently not logged in."
+msgstr "You are currently not logged in."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "You are logged in as ''{0}''."
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr "You are not logged in, please log in to Mapillary in the preferences"
+
+msgid "You are not logged in, please log in to Streetside in the preferences"
+msgstr "You are not logged in, please log in to Streetside in the preferences"
+
+msgid "Zoom to selected image"
+msgstr "Zoom to selected image"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Zoom to the currently selected Mapillary image"
+
+msgid "Zoom to the currently selected Streetside image"
+msgstr "Zoom to the currently selected Streetside image"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "areas with downloaded OSM-data"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "everything in the visible area"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "only when manually requested"
+
+msgid "pending"
+msgstr "pending"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr "Allows the user to work with pictures hosted at mapillary.com"
+
+#. Plugin description for Streetside
+msgid "Allows the user to work with pictures hosted at streetside.com"
+msgstr "Allows the user to work with pictures hosted at streetside.com"
+
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/es.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/es.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/es.po	(revision 34317)
@@ -0,0 +1,673 @@
+# Translations for the JOSM plugin 'Mapillary' (es)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: floscher, 2018\n"
+"Language-Team: Spanish (https://www.transifex.com/josm/teams/2544/es/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: es\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgid "2 images joined"
+msgstr "2 imágenes unidas"
+
+msgid "2 images unjoined"
+msgstr "2 imágenes  separadas"
+
+#, java-format
+msgid ""
+"A tag with key <i>{0}</i> is already present on the selected OSM object."
+msgstr ""
+"Una etiqueta con la clave <i>{0}</i> ya está presente en el objeto de OSM "
+"seleccionado."
+
+msgid "Add Mapillary tag"
+msgstr "Añadir etiqueta mapillary"
+
+msgid "All images in a directory"
+msgstr "Todas las imágenes en un directorio"
+
+msgid "All map objects loaded."
+msgstr "Todos los objetos de mapa han sido cargados."
+
+msgid ""
+"An exception occured while trying to submit a changeset. If this happens "
+"repeatedly, consider reporting a bug via the Help menu. If this message "
+"appears for the first time, simply try it again. This might have been an "
+"issue with the internet connection."
+msgstr ""
+"Se produjo una excepción al intentar enviar un conjunto de cambios. Si esto "
+"ocurre repetidamente, considerar reportar un error a través mediante el menú"
+" Ayuda. Si este mensaje aparece por primera vez, simplemente inténtelo de "
+"nuevo. Esto podría haber sido un problema con la conexión de Internet."
+
+msgid "Cancel"
+msgstr "Cancelar"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr "¡El conjunto de cambios  subido falló con {0} errores ''{1} {2}''!"
+
+msgid "Choose signs"
+msgstr "Elegir señales"
+
+msgid "Continues with the paused walk."
+msgstr "Continúa con la caminata pausada."
+
+msgid "Copy key"
+msgstr "Copiar clave"
+
+msgid "Could not import a geotagged image to the Mapillary layer!"
+msgstr "¡No se pudo importar una imagen geoetiquetada a la capa Mapillary!"
+
+#, java-format
+msgid "Could not import the directory ''{0}''!"
+msgstr "¡No se pudo importar el directorio ''{0}''!"
+
+#, java-format
+msgid "Could not import the image ''{0}''!"
+msgstr "¡No se pudo importar la imagen ''{0}''!"
+
+#, java-format
+msgid "Could not open the URL {0} in a browser"
+msgstr "No se pudo abrir la URL {0} en un navegador"
+
+#, java-format
+msgid "Could not read from URL {0}!"
+msgstr "¡No se pudo leer desde la URL {0}!"
+
+msgid "Current Mapillary changeset"
+msgstr "Conjunto de cambios de Mapillary actual"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Cut off sequences at download bounds"
+msgstr "Corta las secuencias en los límites de descargas"
+
+msgid "Days"
+msgstr "Días"
+
+msgid "Delete after upload"
+msgstr "Eliminar después de subir"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "Eliminada {0} imágen"
+msgstr[1] "Eliminadas {0} imágenes"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Mostrar la hora de cuando la fotografía fue tomada."
+
+msgid "Displays detail information on the currently selected Mapillary image"
+msgstr ""
+"Muestra la información detallada sobre la imagen de Mapillary seleccionada"
+
+msgid "Displays objects detected by Mapillary from their street view imagery"
+msgstr ""
+"Muestra objetos detectados por Mapillary a partir de sus imágenes de nivel "
+"de calle"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr ""
+"Muestra la capa donde se visualiza los objetos de mapa detectados por "
+"Mapillary"
+
+#, java-format
+msgid ""
+"Do you really want to replace the current value <i>{0}</i> with the new "
+"value <i>{1}</i>?"
+msgstr ""
+"¿Desea realmente reemplazar el valor actual de <i>{0}</i> con el nuevo valor"
+" <i>{1}</i>?"
+
+msgid "Download Mapillary images in current view"
+msgstr "Descargar imágenes de Mapillary en la vista actual"
+
+msgid "Download mode"
+msgstr "Modo de descarga"
+
+msgid "Downloaded images"
+msgstr "Imágenes descargadas"
+
+msgid "Downloading"
+msgstr "Descargando"
+
+msgid "Downloading Mapillary images"
+msgstr "Descargando imágenes de Mapillary"
+
+msgid "Downloading map objects failed!"
+msgstr "¡La descarga de objetos de mapa ha fallado!"
+
+msgid "Downloading map objects…"
+msgstr "Descargando objetos de mapas..."
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr ""
+"Permitir características beta experimentales (podría comportarse de forma "
+"inestable)"
+
+msgid "Explore"
+msgstr "Explorar"
+
+msgid "Export Mapillary images"
+msgstr "Exportar imágenes Mapillary"
+
+msgid "Export all images"
+msgstr "Exportar todas las imágenes"
+
+msgid "Export selected images"
+msgstr "Exportar las imágenes seleccionadas"
+
+msgid "Export selected sequence"
+msgstr "Exportar la secuencia seleccionada"
+
+msgid "Finished upload"
+msgstr "Carga terminada"
+
+msgid "Follow selected image"
+msgstr "Seguir la imágen seleccionada"
+
+msgid "From existing image layer"
+msgstr "Desde una capa de imágenes existente"
+
+msgid "From which source do you want to import images to the Mapillary layer?"
+msgstr "¿Desde qué origen desea importar las imágenes a la capa Mapillary?"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Ceda el paso"
+
+msgid "Go forward"
+msgstr "Avanzar"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr ""
+"Ir a las preferencias y acceder a Mapillary antes de comenzar con la subida."
+
+msgid "I got it, close this."
+msgstr "Lo tengo, cerrar esto."
+
+msgid "Image actions"
+msgstr "acciones de imagen"
+
+msgid "Image detections"
+msgstr "Detecciones de imágenes"
+
+msgid "Image info"
+msgstr "Información de la imagen"
+
+msgid "Image key"
+msgstr "clave de imagen"
+
+msgid "Images from my file system"
+msgstr "Imágenes de mi sistema de archivos"
+
+msgid "Import"
+msgstr "Importar"
+
+msgid "Import exception"
+msgstr "Excepción de importación"
+
+msgid "Import local pictures"
+msgstr "Importar imágenes locales"
+
+msgid "Import pictures"
+msgstr "Importar imágenes"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Importar imágenes a la capa de Mapillary"
+
+msgid "Imported images"
+msgstr "Imágenes importadas"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "Importada {0} imágen"
+msgstr[1] "Importadas {0} imágenes"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Peligro por intersección"
+
+msgid ""
+"It can be activated by clicking the left button at the bottom of this "
+"message or the button in the toolbar on the left, which uses the same icon."
+msgstr ""
+"Se puede activar haciendo clic en el botón izquierdo en la parte inferior de"
+" este mensaje o en el botón de la barra de herramientas a la izquierda, que "
+"utiliza el mismo icono."
+
+msgid "Join mode"
+msgstr "Modo unión"
+
+msgid "Join/unjoin pictures"
+msgstr "Unir/separar imágenes"
+
+msgid "Jump to blue"
+msgstr "Saltar al azul"
+
+msgid "Jump to red"
+msgstr "Saltar al rojo"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Saltar a la imagen al otro lado de la línea azul"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Saltar a la imagen al otro lado de la línea roja"
+
+msgid "Key copied to clipboard"
+msgstr "Clave copiada al portapapeles"
+
+msgid "Login"
+msgstr "Acceder"
+
+msgid "Login successful, return to JOSM."
+msgstr "Acceso correcto, volver a JOSM."
+
+msgid "Logout"
+msgstr "Cerrar sesión"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Dirección obligatoria (cualquiera)"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Imágenes de Mapillary"
+
+msgid "Mapillary changeset"
+msgstr "Conjunto de cambios de Mapillary"
+
+msgid "Mapillary filter"
+msgstr "Filtro de Mapillary"
+
+msgid "Mapillary history"
+msgstr "Historial de Mapillary"
+
+msgid "Mapillary image"
+msgstr "Imagen Mapillary"
+
+msgid "Mapillary layer"
+msgstr "Capa de Mapillary"
+
+msgid "Mapillary login"
+msgstr "Acceso a Mapillary"
+
+msgid "Mapillary object layer"
+msgstr "Capa de objeto Mapillary"
+
+msgid "Mapillary objects"
+msgstr "Objetos Mapillary"
+
+msgid "Months"
+msgstr "Meses"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr ""
+"Desplazarse a la ubicación de las imágenes con los botones "
+"siguiente/anterior."
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "{0} imagen movida"
+msgstr[1] "{0} imágenes movidas"
+
+msgid "Next picture"
+msgstr "Fotografía siguiente"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "Ninguna entrada"
+
+msgid "No image selected"
+msgstr "Ninguna imagen seleccionada"
+
+msgid "No images found"
+msgstr "No se encontraron las imágenes"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "No rebasar"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "No estacionarse"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "No gire"
+
+msgid "Not Logged in to Mapillary"
+msgstr "No se encuentra conectado a Mapillary"
+
+msgid "Not older than: "
+msgstr "No más antiguas que: "
+
+#. i18n: Spinner label in JOSM settings
+msgid "Number of images to be pre-fetched (forwards and backwards)"
+msgstr "Número de imágenes a ser pre-cargadas (adelante y hacia atrás)"
+
+msgid "Only images with signs"
+msgstr "Solo imágenes con señales"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Abrir el conjunto de cambios de Mapillary actual"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Abrir diálogo del filtro de Mapillary"
+
+msgid "Open Mapillary history dialog"
+msgstr "Abrir el diálogo del historial de Mapillary"
+
+msgid "Open Mapillary layer"
+msgstr "Capa de Open Mapillary"
+
+msgid "Open Mapillary window"
+msgstr "Abrir ventana de Mapillary"
+
+msgid "Pause"
+msgstr "Pausar"
+
+msgid "Pauses the walk."
+msgstr "Pausar la caminata."
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Cruce de peatones"
+
+msgid "Play"
+msgstr "Iniciar"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "Oprima \"{0}\" para descargar imágenes"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Vista previa de imágenes cuando el cursor se sitúa sobre el icono"
+
+msgid "Previous picture"
+msgstr "Fotografía anterior"
+
+msgid "Redo"
+msgstr "Rehacer"
+
+msgid "Reset"
+msgstr "Reiniciar"
+
+msgid "Rewrite imported images"
+msgstr "Reescribir las imágenes importadas"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Rotonda"
+
+msgid "Select a directory"
+msgstr "Seleccionar un directorio"
+
+msgid "Select directory to import images from"
+msgstr "Seleccione el directorio desde el cual importar las imágenes"
+
+msgid "Select mode"
+msgstr "Modo selección"
+
+msgid "Select the images you want to import"
+msgstr "Seleccione las imágenes que desea importar"
+
+msgid "Sequence key"
+msgstr "clave de secuencia"
+
+msgid "Show detections on top of image"
+msgstr "Mostrar las detecciones en la parte superior de la imagen"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Mostrar la imagen siguiente de la secuencia"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Mostrar la imagen previa de la secuencia"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Límite de velocidad"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Stop"
+
+msgid "Stops the walk."
+msgstr "Detiene la caminata."
+
+msgid "Submit changeset"
+msgstr "Enviar conjunto de cambios"
+
+msgid "Submit the current changeset"
+msgstr "Enviar el conjunto de cambios actual"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "Enviar el conjunto de cambios actual a Mapillary"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "Enviando el conjunto de cambios de Mapillary"
+
+msgid "Submitting changeset to server…"
+msgstr "Enviando conjunto de cambios al servidor..."
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Formato de imagen soportados (JPG y PNG)"
+
+msgid "Tag conflict"
+msgstr "Conflicto de etiquetas"
+
+msgid ""
+"The Mapillary layer has stopped downloading images, because the requested "
+"area is too big!"
+msgstr ""
+"La capa de Mapillary ha dejado de descargar imágenes debido a que el área "
+"descargada ¡es muy grande!"
+
+msgid ""
+"The Mapillary plugin now uses a separate panel to display extra information "
+"(like the image key) and actions for the currently selected Mapillary image "
+"(like viewing it in a browser)."
+msgstr ""
+"El complemento Mapillary ahora utiliza un panel separado para mostrar "
+"información adicional (como la clave de la imagen) y acciones para la imagen"
+" de Mapillary seleccionada actualmente (como verla en un navegador web)."
+
+msgid "There are currently no layers with geotagged images!"
+msgstr "¡Actualmente no hay acapas con imágenes geoetiquetadas!"
+
+#, java-format
+msgid ""
+"To solve this problem, you could switch to download mode ''{0}'' and load "
+"Mapillary images for a smaller portion of the map."
+msgstr ""
+"Para resolver este problema, podría cambiar al modo de descarga ''{0}'' y "
+"cargar las imágenes Mapillary para una porción más pequeña del mapa."
+
+msgid ""
+"To solve this problem, you could zoom in and load a smaller area of the map."
+msgstr ""
+"Para resolver este problema, puede acercar la vista y cargar una porción más"
+" pequeña del mapa"
+
+msgid "Too many map objects, zoom in to see all."
+msgstr ""
+"Demasiados objetos de mapa, realice un acercamiento para verlos a todos"
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Imágenes de Mapillary totales: {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "{0} imagen girada"
+msgstr[1] "{0} imágenes giradas"
+
+msgid "Undo"
+msgstr "Deshacer"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Camino irregular"
+
+msgid "Update"
+msgstr "Actualizar"
+
+msgid "Upload selected sequence"
+msgstr "Subir secuencia seleccionada"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Cargando: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "Usar formato de 24 horas."
+
+msgid "User"
+msgstr "Usuario"
+
+msgid "View in browser"
+msgstr "Ver en el navegador"
+
+msgid "Wait for full quality pictures"
+msgstr "Esperar por imágenes de máxima calidad"
+
+msgid "Walk mode"
+msgstr "Modo caminar"
+
+#. i18n: Checkbox label in JOSM settings
+msgid ""
+"When opening Mapillary image in web browser, show the blur editor instead of"
+" the image viewer"
+msgstr ""
+"Al abrir la imagen Mapillary en un navegador web, muestra el editor de "
+"difuminación en lugar del visor de imagen"
+
+msgid "Which image layers do you want to import into the Mapillary layer?"
+msgstr "¿Qué capas de imágenes desea importar a la capa de Mapillary?"
+
+msgid "Years"
+msgstr "Años"
+
+msgid "You are currently not logged in."
+msgstr "Actualmente no se encuentra registrado"
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "Está registrado como ''{0}''."
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr ""
+"No se ha validado. Por favor, inicie sesión de Mapillary en Preferencias"
+
+#, java-format
+msgid "You have successfully uploaded {0} images to mapillary.com"
+msgstr "Subió {0} imágenes a mapillary.com"
+
+msgid "Zoom to selected image"
+msgstr "Zoom dentro de la imagen seleccionada"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Acercar a la imagen seleccionada de Mapillary"
+
+msgid "approved"
+msgstr "aprobado"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "áreas con datos OSM descargados"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "todo en la zona visible"
+
+msgid "image has no key"
+msgstr "la imagen no tiene clave"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "sólo cuando se solicitan manualmente"
+
+msgid "pending"
+msgstr "pendiente"
+
+msgid "rejected"
+msgstr "rechazado"
+
+msgid "sequence has no key"
+msgstr "la secuencia no tiene clave"
+
+msgid "unknown user"
+msgstr "usuario desconocido"
+
+#, java-format
+msgid ""
+"{0}\n"
+"Could not read map objects from URL\n"
+"{1}!"
+msgstr ""
+"{0}\n"
+"No se pudo leer objetos del mapa desde la URL\n"
+"{1}!"
+
+#. i18n: {0} is the layer name, {1} the number of images in it
+#, java-format
+msgid "{0} ({1} images)"
+msgstr "{0} ({1} imágenes)"
+
+#, java-format
+msgid "{0} detections"
+msgstr "{0} detecciones"
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "{0} imágenes descargadas"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "{0} imágenes en total"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{0} imágenes en {1} secuencias"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr ""
+"se enviaron {0} imágenes, clave del conjunto de cambios: {1}, estado: {2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "{0} imágenes importadas"
+
+#, java-format
+msgid "{0} sequences, each containing between {1} and {2} images (ø {3})"
+msgstr "{0} secuencias, cada una contiene entre {1} y {2} imágenes (ø {3})"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr "Permite al usuario trabajar con fotos hospedadas en mapillary.com"
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/fr.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/fr.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/fr.po	(revision 34317)
@@ -0,0 +1,673 @@
+# Translations for the JOSM plugin 'Mapillary' (fr)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Julien Noblet <julien.noblet+github@gmail.com>, 2018\n"
+"Language-Team: French (https://www.transifex.com/josm/teams/2544/fr/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: fr\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+msgid "2 images joined"
+msgstr "2 images assemblées"
+
+msgid "2 images unjoined"
+msgstr "2 images désassemblées"
+
+#, java-format
+msgid ""
+"A tag with key <i>{0}</i> is already present on the selected OSM object."
+msgstr ""
+"Un tag avec la clé <i> {0} </ i> est déjà présent sur l''objet OSM "
+"sélectionné."
+
+msgid "Add Mapillary tag"
+msgstr "Ajouter un tag Mapillary"
+
+msgid "All images in a directory"
+msgstr "Toutes les images dans un répertoire"
+
+msgid "All map objects loaded."
+msgstr "Tous les objets  sont téléchargés."
+
+msgid ""
+"An exception occured while trying to submit a changeset. If this happens "
+"repeatedly, consider reporting a bug via the Help menu. If this message "
+"appears for the first time, simply try it again. This might have been an "
+"issue with the internet connection."
+msgstr ""
+"Une exception s’est produite lors de la tentative d’envoi des modifications."
+" Si cela se produit à plusieurs reprises, pensez à signaler un bug via le "
+"menu Aide. Si ce message apparaît pour la première fois, essayez-le à "
+"nouveau. Cela pourrait avoir été un problème avec la connexion Internet."
+
+msgid "Cancel"
+msgstr "Annuler"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr ""
+"Le téléversement du groupe de modification a échoué avec {0} erreurs \"{1} "
+"{2}\"!"
+
+msgid "Choose signs"
+msgstr "Choisir les panneaux"
+
+msgid "Continues with the paused walk."
+msgstr "Continue la marche arrêtée."
+
+msgid "Copy key"
+msgstr "Copier la clé"
+
+msgid "Could not import a geotagged image to the Mapillary layer!"
+msgstr ""
+"On ne peut pas importer une image géotagguée dans la couche Mapillary!"
+
+#, java-format
+msgid "Could not import the directory ''{0}''!"
+msgstr "Impossible d importer le répertoire \"{0}\"!"
+
+#, java-format
+msgid "Could not import the image ''{0}''!"
+msgstr "Impossible d’importer l’image ''{0}''!"
+
+#, java-format
+msgid "Could not open the URL {0} in a browser"
+msgstr "Impossible d ouvrir l URL {0} dans un navigateur"
+
+#, java-format
+msgid "Could not read from URL {0}!"
+msgstr "Impossible de lire depuis l URL {0}!"
+
+msgid "Current Mapillary changeset"
+msgstr "Groupe de modification Mapillary courant"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Cut off sequences at download bounds"
+msgstr "Couper les séquences aux limites de téléchargement"
+
+msgid "Days"
+msgstr "Jours"
+
+msgid "Delete after upload"
+msgstr "Effacer après l’envoi"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "{0} photo effacée"
+msgstr[1] "{0} photos effacées"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Afficher l''heure de la prise de vue"
+
+msgid "Displays detail information on the currently selected Mapillary image"
+msgstr ""
+"Affiche des informations détaillées sur l’image Mapillary actuellement "
+"sélectionnée"
+
+msgid "Displays objects detected by Mapillary from their street view imagery"
+msgstr ""
+"Affiche les objets détectés par Mapillary à partir de leur image de vue de "
+"rue"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr "Affiche le calque montrant les objets détectés par Mapillary"
+
+#, java-format
+msgid ""
+"Do you really want to replace the current value <i>{0}</i> with the new "
+"value <i>{1}</i>?"
+msgstr ""
+"Voulez-vous vraiment remplacer la valeur actuelle <i>{0}</ i> par la "
+"nouvelle valeur <i>{1}</ i>?"
+
+msgid "Download Mapillary images in current view"
+msgstr "Télécharger des images Mapillary dans la vue actuelle"
+
+msgid "Download mode"
+msgstr "Mode téléchargement"
+
+msgid "Downloaded images"
+msgstr "Photos téléchargées"
+
+msgid "Downloading"
+msgstr "Téléchargement en cours"
+
+msgid "Downloading Mapillary images"
+msgstr "Téléchargement des photos Mapillary en cours"
+
+msgid "Downloading map objects failed!"
+msgstr "Le téléchargement des objets a échoué!"
+
+msgid "Downloading map objects…"
+msgstr "Téléchargement des objets de la carte…"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr ""
+"Activer les beta-fonctionnalités expérimentales (peuvent être instables)"
+
+msgid "Explore"
+msgstr "Explorer"
+
+msgid "Export Mapillary images"
+msgstr "Exporter les images Mapillary"
+
+msgid "Export all images"
+msgstr "Exporter toutes les images"
+
+msgid "Export selected images"
+msgstr "Exporter les images sélectionnées"
+
+msgid "Export selected sequence"
+msgstr "Exporter la séquence sélectionnée"
+
+msgid "Finished upload"
+msgstr "Envoi terminé"
+
+msgid "Follow selected image"
+msgstr "Suivre l''image sélectionnée"
+
+msgid "From existing image layer"
+msgstr "À partir de couche d image existante"
+
+msgid "From which source do you want to import images to the Mapillary layer?"
+msgstr ""
+"De quelle source souhaitez-vous importer des images vers la couche "
+"Mapillary?"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Cédez-le-passage"
+
+msgid "Go forward"
+msgstr "Avancer"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr ""
+"Ouvrez les paramètres et connectez-vous à Mapillary avant de réaliser un "
+"upload."
+
+msgid "I got it, close this."
+msgstr "J’ai compris. Fermez cela."
+
+msgid "Image actions"
+msgstr "Actions sur l’image"
+
+msgid "Image detections"
+msgstr "Détections d image"
+
+msgid "Image info"
+msgstr "Informations de l image"
+
+msgid "Image key"
+msgstr "Clé de l’image"
+
+msgid "Images from my file system"
+msgstr "Images provenant de mon système de fichiers"
+
+msgid "Import"
+msgstr "Importer"
+
+msgid "Import exception"
+msgstr "Exception d import"
+
+msgid "Import local pictures"
+msgstr "Importer des photos locales"
+
+msgid "Import pictures"
+msgstr "Importer des photos"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Importer des photos dans un calque Mapillary"
+
+msgid "Imported images"
+msgstr "Images importées"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "{0} image importée"
+msgstr[1] "{0} images importées"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Danger à l''intersection"
+
+msgid ""
+"It can be activated by clicking the left button at the bottom of this "
+"message or the button in the toolbar on the left, which uses the same icon."
+msgstr ""
+"Il peut être activé en cliquant sur le bouton gauche en bas de ce message ou"
+" sur le bouton dans la barre d''outils à gauche, qui utilise la même icône."
+
+msgid "Join mode"
+msgstr "Mode assemblage"
+
+msgid "Join/unjoin pictures"
+msgstr "(Dés)assembler les images"
+
+msgid "Jump to blue"
+msgstr "Aller en bleu"
+
+msgid "Jump to red"
+msgstr "Aller en rouge"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Passer à l’image de l’autre côté de la ligne bleue"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Passer à l’image de l’autre côté de la ligne rouge"
+
+msgid "Key copied to clipboard"
+msgstr "Copier dans le Presse-papier"
+
+msgid "Login"
+msgstr "Connexion"
+
+msgid "Login successful, return to JOSM."
+msgstr "Connexion réussie, retour à JOSM."
+
+msgid "Logout"
+msgstr "Déconnexion"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Prescription de sens (n''importe lequel)"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Images Mapillary"
+
+msgid "Mapillary changeset"
+msgstr "Modifications Mapillary"
+
+msgid "Mapillary filter"
+msgstr "Filtre Mapillary"
+
+msgid "Mapillary history"
+msgstr "Historique de Mapillary"
+
+msgid "Mapillary image"
+msgstr "image Mapillary"
+
+msgid "Mapillary layer"
+msgstr "Calque Mapillary"
+
+msgid "Mapillary login"
+msgstr "Connexion à Mapillary"
+
+msgid "Mapillary object layer"
+msgstr "Calque d''objets Mapillary"
+
+msgid "Mapillary objects"
+msgstr "Objets Mapillary"
+
+msgid "Months"
+msgstr "Mois"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr ""
+"Centrer la vue sur la localisation de la photo avec les boutons "
+"suivante/précédente"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "{0} image déplacée"
+msgstr[1] "{0} images déplacées"
+
+msgid "Next picture"
+msgstr "Photo suivante"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "Aucune entrée"
+
+msgid "No image selected"
+msgstr "Pas d''image sélectionnée"
+
+msgid "No images found"
+msgstr "Aucune image trouvée"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "Interdiction de dépasser"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "Stationnement interdit"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "Changement de direction interdit"
+
+msgid "Not Logged in to Mapillary"
+msgstr "Non connecté a Mapillary"
+
+msgid "Not older than: "
+msgstr "Pas plus vieux que : "
+
+#. i18n: Spinner label in JOSM settings
+msgid "Number of images to be pre-fetched (forwards and backwards)"
+msgstr "Nombre d images a pré-charger (vers l avant, vers l arrière)"
+
+msgid "Only images with signs"
+msgstr "Seulement les images avec panneaux"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Ouvrir la boite de dialogue des modifications Mapillary"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Ouvrir le dialogue du filtre Mapillary"
+
+msgid "Open Mapillary history dialog"
+msgstr "Ouvrir la fenêtre d''historique de Mapillary"
+
+msgid "Open Mapillary layer"
+msgstr "Ouvrir la couche Mapillary"
+
+msgid "Open Mapillary window"
+msgstr "Ouvrir la fenêtre Mapillary"
+
+msgid "Pause"
+msgstr "Pause"
+
+msgid "Pauses the walk."
+msgstr "Suspend la marche."
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Passage piéton"
+
+msgid "Play"
+msgstr "Lecture"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "Appuyez sur \"{0}\" pour télécharger des images"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Aperçu des images lors du survol de l’icône"
+
+msgid "Previous picture"
+msgstr "Photo précédente"
+
+msgid "Redo"
+msgstr "Répéter"
+
+msgid "Reset"
+msgstr "Rétablir"
+
+msgid "Rewrite imported images"
+msgstr "Réécrire les images importées"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Giratoire"
+
+msgid "Select a directory"
+msgstr "Sélectionner un répertoire"
+
+msgid "Select directory to import images from"
+msgstr "Sélectionnez le répertoire pour importer des images de"
+
+msgid "Select mode"
+msgstr "Choisir un mode"
+
+msgid "Select the images you want to import"
+msgstr "Sélectionnez les images que vous souhaitez importer"
+
+msgid "Sequence key"
+msgstr "Clé de la séquence"
+
+msgid "Show detections on top of image"
+msgstr "Montre les détections en haut de l image"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Voir la photo suivante"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Voir la photo précédente"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Limite de vitesse"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Stop"
+
+msgid "Stops the walk."
+msgstr "Arrête la marche."
+
+msgid "Submit changeset"
+msgstr "Soumettez les changements"
+
+msgid "Submit the current changeset"
+msgstr "Soumettez l’ensemble des modifications actuelles"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "Soumettre le groupe de modification courant a Mapillary"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "Groupe de modification Mpaillary en cours d envoi"
+
+msgid "Submitting changeset to server…"
+msgstr "Envoyer les modifications au serveur ..."
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Formats d''image supportés (JPG et PNG)"
+
+msgid "Tag conflict"
+msgstr "Tag en conflit"
+
+msgid ""
+"The Mapillary layer has stopped downloading images, because the requested "
+"area is too big!"
+msgstr ""
+"Le calque Mapillary a arrêté de télécharger les images parce que la zone "
+"demandée est trop grande!"
+
+msgid ""
+"The Mapillary plugin now uses a separate panel to display extra information "
+"(like the image key) and actions for the currently selected Mapillary image "
+"(like viewing it in a browser)."
+msgstr ""
+"Le plugin Mapillary utilise maintenant un panneau séparé pour afficher des "
+"informations supplémentaires (comme la clé d''image) et les actions pour "
+"l''image Mapillary sélectionnée (comme l''afficher dans un navigateur)."
+
+msgid "There are currently no layers with geotagged images!"
+msgstr "Il n''y a actuellement aucun calque avec des images géoréférencées!"
+
+#, java-format
+msgid ""
+"To solve this problem, you could switch to download mode ''{0}'' and load "
+"Mapillary images for a smaller portion of the map."
+msgstr ""
+"Pour résoudre ce problème, vous pouvez passer sur le mode de téléchargement "
+"\"{0}\" et charger les images Mapillary pour une zone de la carte plus "
+"restreinte."
+
+msgid ""
+"To solve this problem, you could zoom in and load a smaller area of the map."
+msgstr ""
+"Pour résoudre ce problème, vous pouvez zoomer et charger une zone plus "
+"restreinte de la carte."
+
+msgid "Too many map objects, zoom in to see all."
+msgstr "Tous les objets ne peuvent être affichés, zoomez pour voir tout."
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Nombre total de photos : {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "{0} image tournée"
+msgstr[1] "{0} images tournées"
+
+msgid "Undo"
+msgstr "Annuler"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Route déformée"
+
+msgid "Update"
+msgstr "Mettre à jour"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Envoi en cours : {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "Utiliser le système horaire sur 24 heures"
+
+msgid "User"
+msgstr "Utilisateur"
+
+msgid "View in browser"
+msgstr "Voir dans le navigateur"
+
+msgid "Wait for full quality pictures"
+msgstr "Attendre les images en pleine résolution"
+
+msgid "Walk mode"
+msgstr "Mode piéton"
+
+#. i18n: Checkbox label in JOSM settings
+msgid ""
+"When opening Mapillary image in web browser, show the blur editor instead of"
+" the image viewer"
+msgstr ""
+"A l’ouverture d’une image dans le navigateur, ouvrir l’éditeur de floutage "
+"au lieu du visualiseur d’images"
+
+msgid "Which image layers do you want to import into the Mapillary layer?"
+msgstr ""
+"Quelles couches d''image souhaitez-vous importer dans la couche Mapillary?"
+
+msgid "Years"
+msgstr "Années"
+
+msgid "You are currently not logged in."
+msgstr "Vous n''êtes pas identifié."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "Vous êtes connecté en tant que ''{0}''."
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr ""
+"Vous n êtes pas connecté, connectez vous a Mapillary dans les préférences"
+
+#, java-format
+msgid "You have successfully uploaded {0} images to mapillary.com"
+msgstr "Vous avez chargé avec succès {0} images sur mapillary.com"
+
+msgid "Zoom to selected image"
+msgstr "Zoomer sur l’image sélectionnée"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Zoomer sur l’image Mapillary actuellement sélectionnée"
+
+msgid "approved"
+msgstr "approuvé"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "Zones avec données OSM téléchargées"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "Tout est dans la zone visible"
+
+msgid "image has no key"
+msgstr "L,’image n’a pas de clé"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "Uniquement lorsque demandé manuellement"
+
+msgid "pending"
+msgstr "en attente"
+
+msgid "rejected"
+msgstr "rejeté"
+
+msgid "sequence has no key"
+msgstr "La séquence n’a pas de clé"
+
+msgid "unknown user"
+msgstr "Utilisateur inconnu"
+
+#, java-format
+msgid ""
+"{0}\n"
+"Could not read map objects from URL\n"
+"{1}!"
+msgstr ""
+"{0}\n"
+"Impossible de lire les objets de la carte depuis l URL\n"
+"{1}!"
+
+#. i18n: {0} is the layer name, {1} the number of images in it
+#, java-format
+msgid "{0} ({1} images)"
+msgstr "{0} ({1} images)"
+
+#, java-format
+msgid "{0} detections"
+msgstr "{0} détections"
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "{0} images téléchargées"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "{0} images au total"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{0} images dans {1} séquences"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr "{0} images soumises, Groupe de modification clef: {1}, Etat: {2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "{0} images importées"
+
+#, java-format
+msgid "{0} sequences, each containing between {1} and {2} images (ø {3})"
+msgstr "{0} séquences, chacune contenant entre {1} et {2} images  (ø {3})"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr "Donne accès aux photos hébergées sur mapillary.com"
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/hu.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/hu.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/hu.po	(revision 34317)
@@ -0,0 +1,561 @@
+# Translations for the JOSM plugin 'Mapillary' (hu)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Gábor Babos <gabor.babos@gmail.com>, 2018\n"
+"Language-Team: Hungarian (https://www.transifex.com/josm/teams/2544/hu/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: hu\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgid "2 images joined"
+msgstr "2 két összekapcsolva"
+
+msgid "2 images unjoined"
+msgstr "2 kép szétválasztva"
+
+msgid "Add Mapillary tag"
+msgstr "Mapillary címke hozzáadása"
+
+msgid "All images in a directory"
+msgstr "Egy könyvtár összes képe"
+
+msgid "All map objects loaded."
+msgstr "Az összes térképobjektum betöltve."
+
+msgid "Cancel"
+msgstr "Mégse"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr "A módosításcsomag feltöltése meghiúsult, hibakód: {0}, „{1} {2}”"
+
+msgid "Choose signs"
+msgstr "Táblák kiválasztása"
+
+msgid "Continues with the paused walk."
+msgstr "Folytatja a szüneteltetett sétát."
+
+msgid "Copy key"
+msgstr "Kulcs másolása"
+
+msgid "Could not import a geotagged image to the Mapillary layer!"
+msgstr "Nem sikerült a geocímkézett kép importlása a Mapillary rétegre!"
+
+#, java-format
+msgid "Could not import the directory ''{0}''!"
+msgstr "A(z) „{0}” könyvtár nem importálható."
+
+#, java-format
+msgid "Could not import the image ''{0}''!"
+msgstr "A(z) „{0}” kép nem importálható."
+
+#, java-format
+msgid "Could not open the URL {0} in a browser"
+msgstr "A(z) {0} URL nem nyitható meg böngészőben"
+
+msgid "Current Mapillary changeset"
+msgstr "Jelenlegi Mapillary módosításcsomag"
+
+msgid "Days"
+msgstr "Nap"
+
+msgid "Delete after upload"
+msgstr "Feltöltés után törlés"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "{0} kép törölve"
+msgstr[1] "{0} kép törölve"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Kép készítési idejének megjelenítése"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr "Megjeleníti a Mapillary által észlelt térképobjektumokat"
+
+msgid "Download Mapillary images in current view"
+msgstr "Mapillary képek letöltése a jelenlegi nézetben"
+
+msgid "Download mode"
+msgstr "Letöltési mód"
+
+msgid "Downloaded images"
+msgstr "Letöltött képek"
+
+msgid "Downloading"
+msgstr "Letöltés"
+
+msgid "Downloading Mapillary images"
+msgstr "Mapillary képek letöltése"
+
+msgid "Downloading map objects failed!"
+msgstr "A térképobjektumok letöltése sikertelen."
+
+msgid "Downloading map objects…"
+msgstr "Összes térképobjektum letöltése…"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr "Kísérleti béta funkciók engedélyezése (lehet hogy nem stabilak)"
+
+msgid "Explore"
+msgstr "Böngészés"
+
+msgid "Export Mapillary images"
+msgstr "Mapillary képek exportálása"
+
+msgid "Export all images"
+msgstr "Összes kép exportálása"
+
+msgid "Export selected images"
+msgstr "Kijelölt képek exportálása"
+
+msgid "Export selected sequence"
+msgstr "Kijelölt sorozat exportálása"
+
+msgid "Finished upload"
+msgstr "Feltöltés befejeződött"
+
+msgid "Follow selected image"
+msgstr "Kijelölt kép követése"
+
+msgid "From existing image layer"
+msgstr "Létező képrétegről"
+
+msgid "From which source do you want to import images to the Mapillary layer?"
+msgstr "Melyik forrásból akarsz képeket importálni a Mapillary rétegre?"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Elsőbbségadás kötelező"
+
+msgid "Go forward"
+msgstr "Előre"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr ""
+"A feltöltés előtt menj a beállításokba és jelentkezz be a Mapillary "
+"fiókodba."
+
+msgid "I got it, close this."
+msgstr "Rendben, bezárás"
+
+msgid "Image actions"
+msgstr "Képműveletek"
+
+msgid "Image detections"
+msgstr "Képészlelések"
+
+msgid "Image info"
+msgstr "Képinformációk"
+
+msgid "Image key"
+msgstr "Képkulcs"
+
+msgid "Images from my file system"
+msgstr "Képek a fájlrendszerről"
+
+msgid "Import"
+msgstr "Importálás"
+
+msgid "Import exception"
+msgstr "Importálási kivétel"
+
+msgid "Import local pictures"
+msgstr "Helyi képek importálása"
+
+msgid "Import pictures"
+msgstr "Képek importálása"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Képek importálása a Mapillary rétegre"
+
+msgid "Imported images"
+msgstr "Importált képek"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "{0} kép importálva"
+msgstr[1] "{0} kép importálva"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Veszélyes útkereszteződés"
+
+msgid "Join mode"
+msgstr "Összekapcsolási mód"
+
+msgid "Join/unjoin pictures"
+msgstr "Képek össze-/szétkapcsolása"
+
+msgid "Jump to blue"
+msgstr "Kékhez ugrás"
+
+msgid "Jump to red"
+msgstr "Piroshoz ugrás"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "A kék vonal végén lévő képhez ugrik"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "A piros vonal végén lévő képhez ugrik"
+
+msgid "Key copied to clipboard"
+msgstr "Kulcs vágólapra másolva"
+
+msgid "Login"
+msgstr "Belépés"
+
+msgid "Login successful, return to JOSM."
+msgstr "Bejelentkezés sikeres, vissza a JOSM-hez."
+
+msgid "Logout"
+msgstr "Kijelentkezés"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Kötelező haladási irány"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Mapillary képek"
+
+msgid "Mapillary changeset"
+msgstr "Mapillary módosításcsomag"
+
+msgid "Mapillary filter"
+msgstr "Mapillary szűrő"
+
+msgid "Mapillary history"
+msgstr "Mapillary előzmények"
+
+msgid "Mapillary layer"
+msgstr "Mapillary réteg"
+
+msgid "Mapillary login"
+msgstr "Mapillary bejelentkezés"
+
+msgid "Mapillary object layer"
+msgstr "Mapillary objektumréteg"
+
+msgid "Mapillary objects"
+msgstr "Mapillary objektumok"
+
+msgid "Months"
+msgstr "Hónap"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr "Képhez ugrás az előző/következő gomb megnyomásakor"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "{0} kép áthelyezve"
+msgstr[1] "{0} kép áthelyezve"
+
+msgid "Next picture"
+msgstr "Következő kép"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "Behajtani tilos"
+
+msgid "No image selected"
+msgstr "Nincs kép kijelölve"
+
+msgid "No images found"
+msgstr "Nem található kép"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "Előzni tilos"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "Várakozni tilos"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "Bekanyarodni tilos"
+
+msgid "Not Logged in to Mapillary"
+msgstr "Nem vagy bejelentkezve Mapillary-be"
+
+msgid "Not older than: "
+msgstr "Nem régebbi mint: "
+
+#. i18n: Spinner label in JOSM settings
+msgid "Number of images to be pre-fetched (forwards and backwards)"
+msgstr "Előtöltendő képek száma (előre és hátra)"
+
+msgid "Only images with signs"
+msgstr "Csak jelzőtáblás képek"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Mapillary módosításcsomag párbeszédablak megnyitása"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Mapillary szűrő párbeszédablak megnyitása"
+
+msgid "Open Mapillary history dialog"
+msgstr "Mapillary előzmény-párbeszédablak megnyitása"
+
+msgid "Open Mapillary layer"
+msgstr "Mapillary réteg megnyitása"
+
+msgid "Open Mapillary window"
+msgstr "Mapillary-ablak megnyitása"
+
+msgid "Pause"
+msgstr "Szünet"
+
+msgid "Pauses the walk."
+msgstr "Szünetelteti a sétát."
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Gyalogosátkelő"
+
+msgid "Play"
+msgstr "Lejátszás"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "Képek letöltéséhez nyomd meg a következőt: ''{0}''"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Kép előnézete, ha az egér az ikon fölött áll"
+
+msgid "Previous picture"
+msgstr "Előző kép"
+
+msgid "Redo"
+msgstr "Újra"
+
+msgid "Reset"
+msgstr "Alaphelyzet"
+
+msgid "Rewrite imported images"
+msgstr "Importált képek átírása"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Körforgalom"
+
+msgid "Select a directory"
+msgstr "Könyvtár kijelölése"
+
+msgid "Select directory to import images from"
+msgstr "Az importálandó képeket tartalmazó könyvtár kijelölése"
+
+msgid "Select mode"
+msgstr "Kijelölés mód"
+
+msgid "Select the images you want to import"
+msgstr "Importálandó képek kijelölése"
+
+msgid "Sequence key"
+msgstr "Sorozat kulcs"
+
+msgid "Show detections on top of image"
+msgstr "Észlelések jelzése a kép tetején"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Megmutatja a sorozat következő képét"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Megmutatja a sorozat előző képét"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Sebességkorlátozás"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Stoptábla"
+
+msgid "Stops the walk."
+msgstr "Séta megállítása"
+
+msgid "Submit changeset"
+msgstr "Módosításcsomag beküldése"
+
+msgid "Submit the current changeset"
+msgstr "Jelenlegi módosításcsomag beküldése"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "Jelenlegi módosításcsomag beküldése a Mapillary-re"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "Mapillary módosításcsomagok beküldése"
+
+msgid "Submitting changeset to server…"
+msgstr "Módosításcsomag elküldése a kiszolgálónak…"
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Támogatott képformátumok (JPG és PNG)"
+
+msgid "Tag conflict"
+msgstr "Címkeütközés"
+
+msgid "There are currently no layers with geotagged images!"
+msgstr "Jelenleg nincsenek geocímkézett képrétegek."
+
+msgid "Too many map objects, zoom in to see all."
+msgstr "Túl sok térképobjektum, nagyíts hogy lásd mindet."
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Összes Mapillary kép: {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "{0} kép elfordítva"
+msgstr[1] "{0} kép elfordítva"
+
+msgid "Undo"
+msgstr "Visszavonás"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Egyenetlen úttest"
+
+msgid "Update"
+msgstr "Frissítés"
+
+msgid "Upload selected sequence"
+msgstr "Kijelölt sorozat feltöltése"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Feltöltés: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "24 órás formátum használata"
+
+msgid "User"
+msgstr "Felhasználó"
+
+msgid "View in browser"
+msgstr "Megtekintés böngészőben"
+
+msgid "Wait for full quality pictures"
+msgstr "Várj a teljes minőségű képekre"
+
+msgid "Walk mode"
+msgstr "Gyalogos mód"
+
+msgid "Which image layers do you want to import into the Mapillary layer?"
+msgstr "Melyik képréteget akarod beimportálni a Mapillary rétegre?"
+
+msgid "Years"
+msgstr "Év"
+
+msgid "You are currently not logged in."
+msgstr "Jelenleg nem vagy bejelentkezve."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "Be vagy jelentkezve „{0}” néven."
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr ""
+"Nem vagy bejelentkezve. Kérlek jelentkezz be Mapillary-be a beállításokban"
+
+#, java-format
+msgid "You have successfully uploaded {0} images to mapillary.com"
+msgstr "Sikeresen feltöltöttél {0} képet a mapillary.com-ra"
+
+msgid "Zoom to selected image"
+msgstr "Nagyítás a kijelölt képre"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Nagyítás a jelenleg kijelölt Mapillary képre"
+
+msgid "approved"
+msgstr "elfogadva"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "letöltött OSM-adatokat tartalmazó területek"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "minden, a látható területen"
+
+msgid "image has no key"
+msgstr "a képnek nincs kulcsa"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "csak kézi lekérésre"
+
+msgid "pending"
+msgstr "függőben"
+
+msgid "rejected"
+msgstr "elutasítva"
+
+msgid "unknown user"
+msgstr "ismeretlen felhasználó"
+
+#. i18n: {0} is the layer name, {1} the number of images in it
+#, java-format
+msgid "{0} ({1} images)"
+msgstr "{0} ({1} kép)"
+
+#, java-format
+msgid "{0} detections"
+msgstr "{0} észlelés"
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "{0} letöltött kép"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "{0} kép összesen"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{0} kép {1} sorozatban"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr "{0} kép beküldve, Módosításcsomag kulcsa: {1}, Állapot: {2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "{0} importált kép"
+
+#, java-format
+msgid "{0} sequences, each containing between {1} and {2} images (ø {3})"
+msgstr "{0} sorozat, egyenként {1} és {2} közti képpel (ø {3})"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr "Lehetővé teszi a mapillary.com fotóinak használatát"
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/nl.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/nl.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/nl.po	(revision 34317)
@@ -0,0 +1,654 @@
+# Translations for the JOSM plugin 'Mapillary' (nl)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: floscher, 2018\n"
+"Language-Team: Dutch (https://www.transifex.com/josm/teams/2544/nl/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: nl\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgid "2 images joined"
+msgstr "2 afbeeldingen samengevoegd"
+
+msgid "2 images unjoined"
+msgstr "2 afbeeldingen van elkaar losgemaakt"
+
+#, java-format
+msgid ""
+"A tag with key <i>{0}</i> is already present on the selected OSM object."
+msgstr ""
+"Een tag met de sleutel <i>{0}</i> is al aanwezig op het geselecteerde object"
+" van OSM."
+
+msgid "Add Mapillary tag"
+msgstr "Tag voor Mapillary toevoegen"
+
+msgid "All images in a directory"
+msgstr "Alle afbeeldingen in een map"
+
+msgid "All map objects loaded."
+msgstr "Alle kaartobjecten geladen."
+
+msgid ""
+"An exception occured while trying to submit a changeset. If this happens "
+"repeatedly, consider reporting a bug via the Help menu. If this message "
+"appears for the first time, simply try it again. This might have been an "
+"issue with the internet connection."
+msgstr ""
+"er trad een uitzondering op tijdens het indienen van de wijzigingenset. Als "
+"dit vaker voorkomt, overweeg dan om een bug te rapporteren via het menu "
+"Help. Als dit bericht voor de eerste keer verschijnt, probeer het dan gewoon"
+" nog een keer. Dit zou een probleempje met de internetverbinding geweest "
+"kunnen zijn."
+
+msgid "Cancel"
+msgstr "Annuleren"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr "Uploaden van wijzigingenset mislukt met {0} fout ''{1} {2}''!"
+
+msgid "Choose signs"
+msgstr "Tekens kiezen"
+
+msgid "Continues with the paused walk."
+msgstr "Doorgaan met onderbroken wandeling"
+
+msgid "Copy key"
+msgstr "Sleutel kopiëren"
+
+msgid "Could not import a geotagged image to the Mapillary layer!"
+msgstr ""
+"Kon geen afbeelding met geoverwijzingen importeren in de laag van Mapillary!"
+
+#, java-format
+msgid "Could not import the directory ''{0}''!"
+msgstr "Kon de map ''{0}'' niet importeren!"
+
+#, java-format
+msgid "Could not import the image ''{0}''!"
+msgstr "Kon de afbeelding ''{0}'' niet importeren!"
+
+#, java-format
+msgid "Could not open the URL {0} in a browser"
+msgstr "Kon de URL {0} niet openen in een browser"
+
+#, java-format
+msgid "Could not read from URL {0}!"
+msgstr "Kon niet lezen vanuit de URL {0}!"
+
+msgid "Current Mapillary changeset"
+msgstr "Huidige wijzigingenset voor Mapillary"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Cut off sequences at download bounds"
+msgstr "Snijd reeksen af op de randen van de download"
+
+msgid "Days"
+msgstr "Dagen"
+
+msgid "Delete after upload"
+msgstr "Na uploaden verwijderen"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "{0} afbeelding verwijderd"
+msgstr[1] "{0} afbeeldingen verwijderd"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Uur weergeven van wanneer de afbeelding werd gemaakt"
+
+msgid "Displays detail information on the currently selected Mapillary image"
+msgstr ""
+"Geeft gedetailleerde informatie weer over de momenteel geselecteerde "
+"afbeelding in Mapillary"
+
+msgid "Displays objects detected by Mapillary from their street view imagery"
+msgstr ""
+"Laat objecten zien die zijn gedetecteerd door Mapillary vanuit hun "
+"straatweergaven"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr ""
+"Geeft de laag weer die de kaartobjecten weergeeft die zijn gedetecteerd door"
+" Mapillary"
+
+#, java-format
+msgid ""
+"Do you really want to replace the current value <i>{0}</i> with the new "
+"value <i>{1}</i>?"
+msgstr ""
+"Wilt u echt de huidige waarde <i>{0}</i> vervangen door de nieuwe waarde "
+"<i>{1}</i>?"
+
+msgid "Download Mapillary images in current view"
+msgstr "Afbeeldingen van Mapillary in huidige weergave downloaden"
+
+msgid "Download mode"
+msgstr "Modus Downloaden"
+
+msgid "Downloaded images"
+msgstr "Gedownloade afbeeldingen"
+
+msgid "Downloading"
+msgstr "Downloaden"
+
+msgid "Downloading Mapillary images"
+msgstr "Afbeeldingen van Mapillary downloaden"
+
+msgid "Downloading map objects failed!"
+msgstr "Downloaden van kaartobjecten is mislukt!"
+
+msgid "Downloading map objects…"
+msgstr "Kaartobjecten downloaden…"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr "Experimentele bèta-mogelijkheden inschakelen (kunnen onstabiel zijn)"
+
+msgid "Explore"
+msgstr "Verkennen"
+
+msgid "Export all images"
+msgstr "Alle afbeeldingen exporteren"
+
+msgid "Export selected images"
+msgstr "Geselecteerde afbeeldingen exporteren"
+
+msgid "Export selected sequence"
+msgstr "Geselecteerde reeks exporteren"
+
+msgid "Finished upload"
+msgstr "Uploaden voltooid"
+
+msgid "Follow selected image"
+msgstr "Geselecteerde afbeelding volgen"
+
+msgid "From existing image layer"
+msgstr "Uit bestaande afbeeldingslaag"
+
+msgid "From which source do you want to import images to the Mapillary layer?"
+msgstr ""
+"Vanuit welke bron wilt u afbeeldingen importeren naar de laag van Mapillary?"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Voorrang verlenen"
+
+msgid "Go forward"
+msgstr "Naar voren gaan"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr "Ga naar Instellingen en log in bij Mapillary vóór uploaden."
+
+msgid "I got it, close this."
+msgstr "Ik snap het, sluit dit venster."
+
+msgid "Image actions"
+msgstr "Acties voor afbeelding"
+
+msgid "Image detections"
+msgstr "Detecties in afbeelding"
+
+msgid "Image info"
+msgstr "Informatie over afbeelding"
+
+msgid "Image key"
+msgstr "Sleutel voor afbeelding"
+
+msgid "Images from my file system"
+msgstr "Afbeeldingen vanaf mijn bestandssysteem"
+
+msgid "Import"
+msgstr "Importeren"
+
+msgid "Import exception"
+msgstr "Uitzondering bij importeren"
+
+msgid "Import local pictures"
+msgstr "Lokale afbeeldingen importeren"
+
+msgid "Import pictures"
+msgstr "Afbeeldingen importeren"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Afbeeldingen naar laag van Mapillary importeren"
+
+msgid "Imported images"
+msgstr "Geïmporteerde afbeeldingen"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "{0} afbeelding geïmporteerd"
+msgstr[1] "{0} afbeeldingen geïmporteerd"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Gevaar: kruising"
+
+msgid ""
+"It can be activated by clicking the left button at the bottom of this "
+"message or the button in the toolbar on the left, which uses the same icon."
+msgstr ""
+"Het kan worden geactiveerd door te klikken op de linker knop aan de "
+"onderzijde van dit bericht of de knop links in de werkbalk, die hetzelfde "
+"pictogram gebruikt."
+
+msgid "Join mode"
+msgstr "Modus Samenvoegen"
+
+msgid "Join/unjoin pictures"
+msgstr "Afbeeldingen samenvoegen/van elkaar losmaken"
+
+msgid "Jump to blue"
+msgstr "Spring naar blauw"
+
+msgid "Jump to red"
+msgstr "Spring naar rood"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Springt naar de afbeelding aan de andere zijde van de blauwe lijn"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Springt naar de afbeelding aan de andere zijde van de rode lijn"
+
+msgid "Key copied to clipboard"
+msgstr "Sleutel gekopieerd naar klembord"
+
+msgid "Login"
+msgstr "Inloggen"
+
+msgid "Login successful, return to JOSM."
+msgstr "Log-in succesvol, terug naar JOSM."
+
+msgid "Logout"
+msgstr "Uitloggen"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Verplichte rijrivchting (altijd)"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Afbeeldingen van Mapillary"
+
+msgid "Mapillary changeset"
+msgstr "Mapillary wijzigingenset"
+
+msgid "Mapillary filter"
+msgstr "filter voor Mapillary"
+
+msgid "Mapillary history"
+msgstr "Geschiedenis Mapillary"
+
+msgid "Mapillary layer"
+msgstr "laag van Mapillary"
+
+msgid "Mapillary login"
+msgstr "Log-in voor Mapillary"
+
+msgid "Mapillary object layer"
+msgstr "Mapillary objectenlaag"
+
+msgid "Mapillary objects"
+msgstr "Objecten van Mapillary"
+
+msgid "Months"
+msgstr "Maanden"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr "Naar locatie van afbeeldingen verplaatsen met knoppen Volgende/Vorige"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "{0} afbeelding verplaatst"
+msgstr[1] "{0} afbeeldingen verplaatst"
+
+msgid "Next picture"
+msgstr "Volgende afbeelding"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "Niet inrijden"
+
+msgid "No image selected"
+msgstr "Geen afbeelding geselecteerd"
+
+msgid "No images found"
+msgstr "Geen afbeeldingen gevonden"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "Niet inhalen"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "Niet parkeren"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "Niet keren"
+
+msgid "Not Logged in to Mapillary"
+msgstr "Niet ingelogd bij Mapillary"
+
+msgid "Not older than: "
+msgstr "Niet ouder dan: "
+
+#. i18n: Spinner label in JOSM settings
+msgid "Number of images to be pre-fetched (forwards and backwards)"
+msgstr ""
+"Aantal afbeeldingen om vooraf op te halen (voorwaarts en achterwaarts)"
+
+msgid "Only images with signs"
+msgstr "Alleen afbeeldingen met tekens"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Dialoogvenster voor wijzigingenset Mapillary openen"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Dialoogvenster voor filter van Mapillary openen"
+
+msgid "Open Mapillary history dialog"
+msgstr "Dialoogvenster Geschiedenis van Mapillary openen"
+
+msgid "Open Mapillary window"
+msgstr "Venster van Mapillary openen"
+
+msgid "Pause"
+msgstr "Pauze"
+
+msgid "Pauses the walk."
+msgstr "Onderbreekt de wandeling"
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Voetgangersoversteekplaats"
+
+msgid "Play"
+msgstr "Afspelen"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "Druk op \"{0}\" om afbeeldingen te downloaden"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Voorbeeld van afbeeldingen bij bevinden boven pictogram"
+
+msgid "Previous picture"
+msgstr "Vorige afbeelding"
+
+msgid "Redo"
+msgstr "Opnieuw uitvoeren"
+
+msgid "Reset"
+msgstr "Herstellen"
+
+msgid "Rewrite imported images"
+msgstr "Geïmporteerde afbeeldingen opnieuw schrijven"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Rotonde"
+
+msgid "Select a directory"
+msgstr "Selecteer een map"
+
+msgid "Select directory to import images from"
+msgstr "Selecteer de map van waaruit u de afbeeldingen wilt importeren"
+
+msgid "Select mode"
+msgstr "Modus Selectie"
+
+msgid "Select the images you want to import"
+msgstr "Selecteer de afbeeldingen die u wilt importeren"
+
+msgid "Sequence key"
+msgstr "Sleutel voor reeks"
+
+msgid "Show detections on top of image"
+msgstr "Detecties bovenop afbeelding weergeven"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Geeft de volgende afbeelding in de reeks weer"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Geeft de vorige afbeelding in de reeks weer"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Maximum snelheid"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Stop"
+
+msgid "Stops the walk."
+msgstr "Stopt de wandeling"
+
+msgid "Submit changeset"
+msgstr "Wijzigingenset indienen"
+
+msgid "Submit the current changeset"
+msgstr "De huidige wijzigingenset indienen"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "De huidige wijzigingenset naar Mapillary indienen"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "Wijzigingenset voor Mapillary indienen"
+
+msgid "Submitting changeset to server…"
+msgstr "Wijzigingenset indienen bij de server…"
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Ondersteunde indelingen voor afbeeldingen (JPG en PNG)"
+
+msgid "Tag conflict"
+msgstr "Tagconflict"
+
+msgid ""
+"The Mapillary layer has stopped downloading images, because the requested "
+"area is too big!"
+msgstr ""
+"De laag van Mapillary is gestopt met downloaden va afbeeldingen omdat het "
+"gevraagde gebied te groot is!"
+
+msgid ""
+"The Mapillary plugin now uses a separate panel to display extra information "
+"(like the image key) and actions for the currently selected Mapillary image "
+"(like viewing it in a browser)."
+msgstr ""
+"De plug-in Mapillary gebruikt nu een afzonderlijk paneel om extra informatie"
+" weer te geven (zoals de sleutel van de afbeelding) en acties voor de "
+"momenteel geselecteerde afbeelding in Mapillary (zoals die bekijken in een "
+"browser)."
+
+msgid "There are currently no layers with geotagged images!"
+msgstr "Er zijn momenteel geen lagen met afbeeldingen met geoverwijzingen!"
+
+#, java-format
+msgid ""
+"To solve this problem, you could switch to download mode ''{0}'' and load "
+"Mapillary images for a smaller portion of the map."
+msgstr ""
+"U zou kunnen schakelen naar de modus Downloaden ''{0}'' en afbeeldingen van "
+"Mapillary kunnen laden voor een kleiner gedeelte van de kaart om dit "
+"probleem op te lossen."
+
+msgid ""
+"To solve this problem, you could zoom in and load a smaller area of the map."
+msgstr ""
+"U zou in kunnen zoomen en een kleiner gedeelte van de kaart kunnen laden om "
+"dit probleem op te lossen."
+
+msgid "Too many map objects, zoom in to see all."
+msgstr "Teveel kaartobjecten, zoom in om ze allemaal te zien."
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Totaal aantal afbeeldingen van Mapillary: {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "{0} afbeelding gedraaid"
+msgstr[1] "{0} afbeeldingen gedraaid"
+
+msgid "Undo"
+msgstr "Ongedaan maken"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Oneven weg"
+
+msgid "Update"
+msgstr "Bijwerken"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Uploaden: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "24-uursindeling gebruiken"
+
+msgid "User"
+msgstr "Gebruiker"
+
+msgid "View in browser"
+msgstr "Weergeven in browser"
+
+msgid "Wait for full quality pictures"
+msgstr "Wachten op afbeeldingen met goede kwaliteit"
+
+msgid "Walk mode"
+msgstr "Modus Wandeling"
+
+msgid "Which image layers do you want to import into the Mapillary layer?"
+msgstr "Welke afbeeldingslagen wilt u importeren in de laag van Mapillary?"
+
+msgid "Years"
+msgstr "Jaren"
+
+msgid "You are currently not logged in."
+msgstr "U bent momenteel niet ingelogd."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "U bent aangemeld als ''{0}''."
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr "U bent niet ingelogd, log in bij Mapillary in de Voorkeuren"
+
+#, java-format
+msgid "You have successfully uploaded {0} images to mapillary.com"
+msgstr "U heeft met succes {0} afbeeldingen naar mapillary.com geüpload"
+
+msgid "Zoom to selected image"
+msgstr "Zoom naar geselecteerde afbeelding"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Zoom naar huidige geselecteerde afbeelding van Mapillary"
+
+msgid "approved"
+msgstr "goedgekeurd"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "gebieden met gedownloade gegevens van OSM"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "alles in het zichtbare gebied"
+
+msgid "image has no key"
+msgstr "afbeelding heeft geen sleutel"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "alleen indien handmatig verzocht"
+
+msgid "pending"
+msgstr "afwachtend"
+
+msgid "rejected"
+msgstr "afgewezen"
+
+msgid "sequence has no key"
+msgstr "reeks heeft geen sleutel"
+
+msgid "unknown user"
+msgstr "onbekende gebruiker"
+
+#, java-format
+msgid ""
+"{0}\n"
+"Could not read map objects from URL\n"
+"{1}!"
+msgstr ""
+"{0}\n"
+"Kon geen kaartobjecten lezen vanuit URL\n"
+"{1}!"
+
+#. i18n: {0} is the layer name, {1} the number of images in it
+#, java-format
+msgid "{0} ({1} images)"
+msgstr "{0} ({1} afbeeldingen)"
+
+#, java-format
+msgid "{0} detections"
+msgstr "{0} detecties"
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "{0} gedownloade afbeeldingen"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "{0} totaal aantal afbeeldingen"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{0} afbeeldingen in {1} reeksen"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr "{0} afbeeldingen ingediend, Sleutel wijzigingenset: {1}, Status: {2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "{0} geïmporteerde afbeeldingen"
+
+#, java-format
+msgid "{0} sequences, each containing between {1} and {2} images (ø {3})"
+msgstr "{0} reeksen, elk tussen {1} en {2} afbeeldingen bevattend (ø {3})"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr ""
+"Stelt de gebruiker in staat om te werken met afbeeldingen die worden gehost "
+"op mapillary.com"
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/pl.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/pl.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/pl.po	(revision 34317)
@@ -0,0 +1,622 @@
+# Translations for the JOSM plugin 'Mapillary' (pl)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: floscher, 2018\n"
+"Language-Team: Polish (https://www.transifex.com/josm/teams/2544/pl/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: pl\n"
+"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
+
+msgid "2 images joined"
+msgstr "2 zdjęcia połączone"
+
+msgid "2 images unjoined"
+msgstr "2 zdjęcia rozłączone"
+
+#, java-format
+msgid ""
+"A tag with key <i>{0}</i> is already present on the selected OSM object."
+msgstr ""
+"Znacznik z kluczem <i>{0}</i> obecnie istnieje w wybranym obiekcie OSM."
+
+msgid "Add Mapillary tag"
+msgstr "Dodaj znacznik Mapillary"
+
+msgid "All images in a directory"
+msgstr "Wszystkie zdjęcia w katalogu"
+
+msgid "All map objects loaded."
+msgstr "Wsyzstkie dane mapy załadowane."
+
+msgid ""
+"An exception occured while trying to submit a changeset. If this happens "
+"repeatedly, consider reporting a bug via the Help menu. If this message "
+"appears for the first time, simply try it again. This might have been an "
+"issue with the internet connection."
+msgstr ""
+"Wystąpił błąd podczas próby wysyłania zestawu zmian. Jeśli powtarza się to "
+"często, zgłoś błąd poprzez menu pomocy. Jeśli wiadomość pojawiła się "
+"pierwszy raz, po prostu spróbuj ponownie. Może wystąpiły jakieś problemy z "
+"połączeniem internetowym."
+
+msgid "Cancel"
+msgstr "Anuluj"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr "Błąd wysyłania zestawu zmian z {0} ''{1} {2}''!"
+
+msgid "Choose signs"
+msgstr "Wybierz znaki:"
+
+msgid "Continues with the paused walk."
+msgstr "Kontynuuje przerwany spacer."
+
+msgid "Copy key"
+msgstr "Kopuj klucz"
+
+msgid "Could not import a geotagged image to the Mapillary layer!"
+msgstr ""
+"Nie można zaimportować zdjęc z zapisaną pozycją GPS do warstwy Mapillary."
+
+#, java-format
+msgid "Could not import the directory ''{0}''!"
+msgstr "Nie można zaimportować katalogu ''{0}''!"
+
+#, java-format
+msgid "Could not import the image ''{0}''!"
+msgstr "Nie można zaimportować zdjęcia ''{0}''!"
+
+#, java-format
+msgid "Could not open the URL {0} in a browser"
+msgstr "Nie można otworzyć adresu URL {0} w przeglądarce"
+
+#, java-format
+msgid "Could not read from URL {0}!"
+msgstr "Nie można odczytać z URL {0}!"
+
+msgid "Current Mapillary changeset"
+msgstr "Obecny zestaw zmian Mapillary"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Cut off sequences at download bounds"
+msgstr "Obetnij sekwencje na granicach pobierania"
+
+msgid "Days"
+msgstr "Dni"
+
+msgid "Delete after upload"
+msgstr "Usuń po wysłaniu"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Wyświetlaj godzinę wykonania zdjęcia."
+
+msgid "Displays detail information on the currently selected Mapillary image"
+msgstr "Wyświetla szczegółowe informacje o obecnie wybranym obrazie Mapillary"
+
+msgid "Displays objects detected by Mapillary from their street view imagery"
+msgstr "Wyświetla obiekty wykryte przez Mapillary z ich podkładu street view"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr "Wyświetla warstwę pokazującą obiekty na mapie wykryte przez Mapillary"
+
+#, java-format
+msgid ""
+"Do you really want to replace the current value <i>{0}</i> with the new "
+"value <i>{1}</i>?"
+msgstr "Na pewno chcesz zamienić obecną wartość <i>{0}</i> nową <i>{1}</i>?"
+
+msgid "Download Mapillary images in current view"
+msgstr "Pobierz obrazy Mapillary w obecnym widoku"
+
+msgid "Download mode"
+msgstr "Tryb pobierania"
+
+msgid "Downloaded images"
+msgstr "Pobrane obrazy:"
+
+msgid "Downloading"
+msgstr "Pobieranie"
+
+msgid "Downloading Mapillary images"
+msgstr "Pobieranie obrazów Mapillary"
+
+msgid "Downloading map objects failed!"
+msgstr "Błąd pobierania elementów mapy!"
+
+msgid "Downloading map objects…"
+msgstr "Pobieranie elementów mapy…"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr "Włącz tryb eksperymentalny (może być niestabilny)"
+
+msgid "Explore"
+msgstr "Przeglądaj"
+
+msgid "Export all images"
+msgstr "Eksportuj wszystkie obrazy"
+
+msgid "Export selected images"
+msgstr "Eksportuj wybrane obrazy"
+
+msgid "Export selected sequence"
+msgstr "Eksportuj wybraną sekwencję"
+
+msgid "Finished upload"
+msgstr "Zakończono wysyłanie"
+
+msgid "Follow selected image"
+msgstr "Podążaj za wybranym zdjęciem"
+
+msgid "From existing image layer"
+msgstr "Z istniejącej warstwy zdjęć"
+
+msgid "From which source do you want to import images to the Mapillary layer?"
+msgstr "Z jakiego źródła chcesz zaimportować zdjęcia do warstwy Mapillary?"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Ustąp pierwszeństwa"
+
+msgid "Go forward"
+msgstr "Idź do przodu"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr "Wejdź w ustawienia i zaloguj się na Mapillary przed wysłaniem."
+
+msgid "I got it, close this."
+msgstr "Zrozumiałem, zamknij okno."
+
+msgid "Image actions"
+msgstr "Akcje zdjęcia"
+
+msgid "Image detections"
+msgstr "Wykrywanie zdjęcia"
+
+msgid "Image info"
+msgstr "Informacje o obrazie"
+
+msgid "Image key"
+msgstr "Klucz zdjęcia"
+
+msgid "Images from my file system"
+msgstr "Zdjęcia z mojego systemu plików"
+
+msgid "Import"
+msgstr "Import"
+
+msgid "Import exception"
+msgstr "Wyjątek importowania"
+
+msgid "Import local pictures"
+msgstr "Importuj lokalne zdjęcia"
+
+msgid "Import pictures"
+msgstr "Importuj zdjęcia"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Importuj zdjęcia na warstwę Mapillary"
+
+msgid "Imported images"
+msgstr "Zaimportowane obrazy"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Niebezpieczne skrzyżowanie"
+
+msgid ""
+"It can be activated by clicking the left button at the bottom of this "
+"message or the button in the toolbar on the left, which uses the same icon."
+msgstr ""
+"Może on zostać aktywowany poprzez naciśnięcie lewego przycisku myszy na "
+"przycisk tej wiadomości lub przycisk na pasku narzędzi po lewej, który używa"
+" takiej samej ikony."
+
+msgid "Join mode"
+msgstr "Tryb łączenia"
+
+msgid "Join/unjoin pictures"
+msgstr "Łączenie/rozłączanie zdjęć"
+
+msgid "Jump to blue"
+msgstr "Skocz do niebieskiego"
+
+msgid "Jump to red"
+msgstr "Skocz do czerwonego"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Przeskakuje do zdjęcia po drugiej stronie niebieskiej linii"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Przeskakuje do zdjęcia po drugiej stronie czerwonej linii"
+
+msgid "Key copied to clipboard"
+msgstr "Klucz skopiowany do schowka"
+
+msgid "Login"
+msgstr "Zaloguj"
+
+msgid "Login successful, return to JOSM."
+msgstr "Zalogowano pomyślnie, powrót do JOSM."
+
+msgid "Logout"
+msgstr "Wyloguj"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Nakaz skrętu"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Obrazy Mapillary"
+
+msgid "Mapillary changeset"
+msgstr "Zestaw zmian Mapillary"
+
+msgid "Mapillary filter"
+msgstr "Filtr Mapillary"
+
+msgid "Mapillary history"
+msgstr "Historia Mapillary"
+
+msgid "Mapillary layer"
+msgstr "Warstwy Mapillary"
+
+msgid "Mapillary login"
+msgstr "Logowanie Mapillary"
+
+msgid "Mapillary object layer"
+msgstr "Warstwa obiektów Mapillary"
+
+msgid "Mapillary objects"
+msgstr "Obiekty Mapillary"
+
+msgid "Months"
+msgstr "Miesiące"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr ""
+"Przesuwaj do lokalizacji zdjęć za pomocą przycisków następny/poprzedni."
+
+msgid "Next picture"
+msgstr "Następne zdjęcie"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "Zakaz wjazdu"
+
+msgid "No image selected"
+msgstr "Nie wybrano obrazu"
+
+msgid "No images found"
+msgstr "Nie znaleziono zdjęć"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "Zakaz wyprzedzania"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "Zakaz postoju"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "Zakaz zawracania"
+
+msgid "Not Logged in to Mapillary"
+msgstr "Nie zalogowany do Mapillary"
+
+msgid "Not older than: "
+msgstr "Nie starsze niż: "
+
+#. i18n: Spinner label in JOSM settings
+msgid "Number of images to be pre-fetched (forwards and backwards)"
+msgstr "Ilość obrazów które mają być wstępnie pobrane (do przodu i tyłu)"
+
+msgid "Only images with signs"
+msgstr "Tylko obrazy ze znakami:"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Otwórz okno zestawu zmian Mapillary"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Otwiera okno filtrów Mapillary"
+
+msgid "Open Mapillary history dialog"
+msgstr "Otwiera okno histori Mapillary"
+
+msgid "Open Mapillary layer"
+msgstr "Otwórz wartwę Mapillary"
+
+msgid "Open Mapillary window"
+msgstr "Otwiera okno Mapillary"
+
+msgid "Pause"
+msgstr "Zatrzymaj"
+
+msgid "Pauses the walk."
+msgstr "Zatrzymuje spacer."
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Przejście dla pieszych"
+
+msgid "Play"
+msgstr "Idź"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "Wciśnij \"{0}\" aby pobrać obrazy"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Podgląd zdjęć po najechaniu na ich ikonę"
+
+msgid "Previous picture"
+msgstr "Poprzednie zdjęcie"
+
+msgid "Redo"
+msgstr "Ponów"
+
+msgid "Reset"
+msgstr "Przywróć domyślne"
+
+msgid "Rewrite imported images"
+msgstr "Przepisz zaimportowane obrazy"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Rondo"
+
+msgid "Select a directory"
+msgstr "Wybierz katalog"
+
+msgid "Select directory to import images from"
+msgstr "Wybierz katalog z którego zaimportować zdjęcia"
+
+msgid "Select mode"
+msgstr "Wybierz tryb"
+
+msgid "Select the images you want to import"
+msgstr "Wybierz zdjęcia które chcesz zaimportować"
+
+msgid "Sequence key"
+msgstr "Klucz sekwencji"
+
+msgid "Show detections on top of image"
+msgstr "Pokaż wykrywanie na górze obrazu"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Pokazuje następne zdjęcie w sekwencji"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Pokazuje poprzednie zdjęcie w sekwencji"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Ograniczenie prędkości"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Znak stop"
+
+msgid "Stops the walk."
+msgstr "Zatrzymaj spacer."
+
+msgid "Submit changeset"
+msgstr "Zatwierdź zestaw zmian"
+
+msgid "Submit the current changeset"
+msgstr "Zatwierdź obecny zestaw zmian"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "Zatwierdź obecny zestaw zmian do Mapillary"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "Wysyłanie zestawu zmian Mapillary"
+
+msgid "Submitting changeset to server…"
+msgstr "Wysyłanie zestawu zmian na serwer…"
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Obsługiwane formaty obrazów (JPG i PNG)"
+
+msgid "Tag conflict"
+msgstr "Konflikt znaczników"
+
+msgid ""
+"The Mapillary layer has stopped downloading images, because the requested "
+"area is too big!"
+msgstr ""
+"Warstwa Mapillary przestała pobierać obrazy, ponieważ żądany obszar jest za "
+"duży!"
+
+msgid ""
+"The Mapillary plugin now uses a separate panel to display extra information "
+"(like the image key) and actions for the currently selected Mapillary image "
+"(like viewing it in a browser)."
+msgstr ""
+"Wtyczka Mapillary uzywa teraz osobnego panelu do wyświetlania dodatkowych "
+"informacji (jak klucz obrazu) i akcji dla obecnie wybranego obrazu Mapillary"
+" (np. wyświetlanie w przeglądarce)."
+
+msgid "There are currently no layers with geotagged images!"
+msgstr "Nie ma obecnie warstw ze zdjęciami z zapisaną pozycją GPS."
+
+#, java-format
+msgid ""
+"To solve this problem, you could switch to download mode ''{0}'' and load "
+"Mapillary images for a smaller portion of the map."
+msgstr ""
+"By rozwiązać ten problem, powinieneś przełączyć na tryb pobierania ''{0}'' i"
+" załadować obrazy Mapillary z mniejszej części mapy."
+
+msgid ""
+"To solve this problem, you could zoom in and load a smaller area of the map."
+msgstr ""
+"By rozwiązać ten problem, powinieneś przybliżyć i załadować mniejszy obszar "
+"mapy."
+
+msgid "Too many map objects, zoom in to see all."
+msgstr "Za dużo elementów mapy, przybliż żeby zobaczyć wszystko."
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Łącznie obrazów Mapillary: {0}"
+
+msgid "Undo"
+msgstr "Cofnij"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Koleiny"
+
+msgid "Update"
+msgstr "Aktualizuj"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Wysyłanie: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "Używaj formatu 24-godzinnego."
+
+msgid "User"
+msgstr "Użytkownik"
+
+msgid "View in browser"
+msgstr "Zobacz w przeglądarce"
+
+msgid "Wait for full quality pictures"
+msgstr "Czekaj na zdjęcia w pełnej rozdzielczości"
+
+msgid "Walk mode"
+msgstr "Tryb spaceru"
+
+#. i18n: Checkbox label in JOSM settings
+msgid ""
+"When opening Mapillary image in web browser, show the blur editor instead of"
+" the image viewer"
+msgstr ""
+"Podczas odwierania obrazu Mapillary w przeglądarce, pokaż edytor rozmazania "
+"zamiast podglądu zdjęcia"
+
+msgid "Which image layers do you want to import into the Mapillary layer?"
+msgstr "Które warstwy zdjęć chcesz zaimportować do warstwy Mapillary?"
+
+msgid "Years"
+msgstr "Lata"
+
+msgid "You are currently not logged in."
+msgstr "Nie jesteś zalogowany."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "Jesteś zalogowany jako \"{0}\"."
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr "Nie jesteś zalogowany, proszę to zrobić w ustawieniach Mapillary"
+
+#, java-format
+msgid "You have successfully uploaded {0} images to mapillary.com"
+msgstr "Pomyślnie wysłano {0} obrazów do mapillary.com"
+
+msgid "Zoom to selected image"
+msgstr "Powiększ do wybranego obrazu"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Powiększ do obecnie wybranego obrazu"
+
+msgid "approved"
+msgstr "przyjęte"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "obszary z pobranymi danymi OSM"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "wszystko w widocznym obszarze"
+
+msgid "image has no key"
+msgstr "obraz nie ma klucza"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "tylko przy ręcznym żądaniu"
+
+msgid "pending"
+msgstr "oczekujące"
+
+msgid "rejected"
+msgstr "odrzucone"
+
+msgid "sequence has no key"
+msgstr "sekwencja nie ma klucza"
+
+msgid "unknown user"
+msgstr "nieznany użytkownik"
+
+#, java-format
+msgid ""
+"{0}\n"
+"Could not read map objects from URL\n"
+"{1}!"
+msgstr ""
+"{0}\n"
+"Nie można odczytać elementów mapy z URL\n"
+"{1}!"
+
+#. i18n: {0} is the layer name, {1} the number of images in it
+#, java-format
+msgid "{0} ({1} images)"
+msgstr "{0} ({1} zdjęć)"
+
+#, java-format
+msgid "{0} detections"
+msgstr "{0} wykryć"
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "{0} pobranych obrazów"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "{0} łącznie obrazów"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{0} obrazów w {1} sekwencjach"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr "{0} zdjęć zatwierdzonych, Klucz zestawu zmian: {1}, stan: {2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "{0} zaimportowanych obrazów"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr "Pozwala użytkownikom używać obrazów przechowywanych na mapillary.com."
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/pt.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/pt.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/pt.po	(revision 34317)
@@ -0,0 +1,612 @@
+# Translations for the JOSM plugin 'Mapillary' (pt)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: floscher, 2018\n"
+"Language-Team: Portuguese (https://www.transifex.com/josm/teams/2544/pt/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: pt\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgid "2 images joined"
+msgstr "2 imagens unidas"
+
+msgid "2 images unjoined"
+msgstr "2 imagens separadas"
+
+#, java-format
+msgid ""
+"A tag with key <i>{0}</i> is already present on the selected OSM object."
+msgstr ""
+"A etiqueta com a chave <i>{0}</i> já existe no objeto do OSM selecionado."
+
+msgid "Add Mapillary tag"
+msgstr "Adicionar etiqueta Mapillary"
+
+msgid "All images in a directory"
+msgstr "Todas as imagens de uma pasta"
+
+msgid "All map objects loaded."
+msgstr "Todos os objetos do mapa carregados."
+
+msgid "Cancel"
+msgstr "Cancelar"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr "O envio do conjunto de alterações falhou com {0} erro ''{1} {2}''!"
+
+msgid "Choose signs"
+msgstr "Escolher sinais"
+
+msgid "Continues with the paused walk."
+msgstr "Continua o modo a pé."
+
+msgid "Copy key"
+msgstr "Copiar chave"
+
+msgid "Could not import a geotagged image to the Mapillary layer!"
+msgstr ""
+"Não foi possível importar a imagem geo-referenciada para a camada Mapillary!"
+
+#, java-format
+msgid "Could not import the directory ''{0}''!"
+msgstr "Não foi possível importar a pasta ''{0}''!"
+
+#, java-format
+msgid "Could not import the image ''{0}''!"
+msgstr "Não foi possível importar a imagem ''{0}''!"
+
+#, java-format
+msgid "Could not open the URL {0} in a browser"
+msgstr "Não foi possível abrir o URL {0} no navegador de internet"
+
+#, java-format
+msgid "Could not read from URL {0}!"
+msgstr "Não foi possível ler do URL {0}!"
+
+msgid "Current Mapillary changeset"
+msgstr "Conjunto de alterações Mapillary atual"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Cut off sequences at download bounds"
+msgstr "Cortar sequências nos limites do descarregamento"
+
+msgid "Days"
+msgstr "Dias"
+
+msgid "Delete after upload"
+msgstr "Eliminar após o envio"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "{0} imagem eliminada"
+msgstr[1] "{0} imagens eliminadas"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Mostrar a hora a que a fotografia foi tirada"
+
+msgid "Displays detail information on the currently selected Mapillary image"
+msgstr ""
+"Mostra informação detalhada sobre a imagem atual selecionada do Mapillary"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr "Mostra a camada com os objetos do mapa detetados pelo Mapillary"
+
+#, java-format
+msgid ""
+"Do you really want to replace the current value <i>{0}</i> with the new "
+"value <i>{1}</i>?"
+msgstr ""
+"Quer mesmo substituir o valor atual <i>{0}</i> com o novo valor <i>{1}</i>?"
+
+msgid "Download Mapillary images in current view"
+msgstr "Descarrregar imagens Mapillary na vista atual"
+
+msgid "Download mode"
+msgstr "Modo de descarregamento"
+
+msgid "Downloaded images"
+msgstr "Imagens descarregadas"
+
+msgid "Downloading"
+msgstr "A descarregar"
+
+msgid "Downloading Mapillary images"
+msgstr "A descarregar imagens Mapillary"
+
+msgid "Downloading map objects failed!"
+msgstr "Não foi possível descarregar objetos do mapa!"
+
+msgid "Downloading map objects…"
+msgstr "A descarregar objetos do mapa..."
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr "Ativar funcionalidades experimentais beta (pode ser instável)"
+
+msgid "Explore"
+msgstr "Explorar"
+
+msgid "Export all images"
+msgstr "Exportar todas as imagens"
+
+msgid "Export selected images"
+msgstr "Exportar imagens selecionadas"
+
+msgid "Export selected sequence"
+msgstr "Exportar sequência selecionada"
+
+msgid "Finished upload"
+msgstr "Envio terminado"
+
+msgid "Follow selected image"
+msgstr "Seguir a imagem selecionada"
+
+msgid "From existing image layer"
+msgstr "Da camada de imagens existente"
+
+msgid "From which source do you want to import images to the Mapillary layer?"
+msgstr "De que fontes quer importar as imagens para a camada Mapillary?"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Cedência de passagem"
+
+msgid "Go forward"
+msgstr "Avançar"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr ""
+"Vá às preferências e autentique-se no Mapillary antes de enviar dados."
+
+msgid "I got it, close this."
+msgstr "Entendido, fechar isto."
+
+msgid "Image actions"
+msgstr "Ações de imagem"
+
+msgid "Image detections"
+msgstr "Deteções de imagem"
+
+msgid "Image info"
+msgstr "Informações da imagem"
+
+msgid "Image key"
+msgstr "Chave da imagem"
+
+msgid "Images from my file system"
+msgstr "Imagens do meu computador"
+
+msgid "Import"
+msgstr "Importar"
+
+msgid "Import exception"
+msgstr "Erro de importação"
+
+msgid "Import local pictures"
+msgstr "Importar imagens locais"
+
+msgid "Import pictures"
+msgstr "Importar imagens"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Importar imagens para a camada Mapillary"
+
+msgid "Imported images"
+msgstr "Imagens importadas"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "{0} imagem importadas"
+msgstr[1] "{0} imagens importadas"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Cruzamento"
+
+msgid "Join mode"
+msgstr "Modo de unir"
+
+msgid "Join/unjoin pictures"
+msgstr "Unir/Separar imagens"
+
+msgid "Jump to blue"
+msgstr "Ir para o azul"
+
+msgid "Jump to red"
+msgstr "Ir para o vermelho"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Mostra a imagem na extremidade da linha azul"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Mostra a imagem na extremidade da linha vermelha"
+
+msgid "Key copied to clipboard"
+msgstr "Chave copiada para a área de transferência"
+
+msgid "Login"
+msgstr "Iniciar sessão"
+
+msgid "Login successful, return to JOSM."
+msgstr "Autenticação bem sucedida, retorne ao JOSM."
+
+msgid "Logout"
+msgstr "Terminar sessão"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Sentido obrigatório"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Imagens Mapillary"
+
+msgid "Mapillary changeset"
+msgstr "Conjunto de alterações Mapillary"
+
+msgid "Mapillary filter"
+msgstr "Filtro Mapillary"
+
+msgid "Mapillary history"
+msgstr "Histórico Mapillary"
+
+msgid "Mapillary layer"
+msgstr "Camada Mapillary"
+
+msgid "Mapillary login"
+msgstr "Autenticação Mapillary"
+
+msgid "Mapillary object layer"
+msgstr "Camada de objetos Mapillary"
+
+msgid "Mapillary objects"
+msgstr "Objetos Mapillary"
+
+msgid "Months"
+msgstr "Meses"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr "Ver a localização da imagem seguinte com os botões seguinte/anterior"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "Movida {0} imagem"
+msgstr[1] "Movidas {0} imagens"
+
+msgid "Next picture"
+msgstr "Imagem seguinte"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "Sentido proibido"
+
+msgid "No image selected"
+msgstr "Nenhuma imagem selecionada"
+
+msgid "No images found"
+msgstr "Nenhuma imagem encontrada"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "Ultrapassagem proibida"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "Estacionamento proibido"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "Proibido virar"
+
+msgid "Not Logged in to Mapillary"
+msgstr "Não autenticado no Mapillary"
+
+msgid "Not older than: "
+msgstr "Não mais antigas que: "
+
+#. i18n: Spinner label in JOSM settings
+msgid "Number of images to be pre-fetched (forwards and backwards)"
+msgstr "Número de imagens a serem pré-carregadas (anteriores e seguintes)"
+
+msgid "Only images with signs"
+msgstr "Apenas imagens com sinais"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Abrir painel de  conjunto de alterações Mapillary"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Abrir janela de filtro Mapillary"
+
+msgid "Open Mapillary history dialog"
+msgstr "Abrir janela do histórico Mapillary"
+
+msgid "Open Mapillary layer"
+msgstr "Abrir camada Mapillary"
+
+msgid "Open Mapillary window"
+msgstr "Abrir janela Mapillary"
+
+msgid "Pause"
+msgstr "Pausa"
+
+msgid "Pauses the walk."
+msgstr "Pausa o modo a pé"
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Passadeira"
+
+msgid "Play"
+msgstr "Iniciar"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "Carregue em \"{0}\" para descarregar as imagens"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Pré-visualizar imagens ao passar com o cursor sobre o ícone"
+
+msgid "Previous picture"
+msgstr "Imagem anterior"
+
+msgid "Redo"
+msgstr "Refazer"
+
+msgid "Reset"
+msgstr "Repor"
+
+msgid "Rewrite imported images"
+msgstr "Tornar a gravar as imagens importadas"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Rotunda"
+
+msgid "Select a directory"
+msgstr "Selecionar diretório"
+
+msgid "Select directory to import images from"
+msgstr "Selecione a pasta com imagens a importar"
+
+msgid "Select mode"
+msgstr "Modo de seleção"
+
+msgid "Select the images you want to import"
+msgstr "Selecione as imagens que quer importar"
+
+msgid "Sequence key"
+msgstr "Chave da sequência"
+
+msgid "Show detections on top of image"
+msgstr "Mostrar deteções por cima da imagem"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Mostra a próxima imagem na sequência de imagens"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Mostra a imagem anterior na sequência de imagens"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Limite de velocidade"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Sinal de Stop"
+
+msgid "Stops the walk."
+msgstr "Pára o modo a pé."
+
+msgid "Submit changeset"
+msgstr "Enviar conjunto de alterações"
+
+msgid "Submit the current changeset"
+msgstr "Enviar conjunto de alterações atual"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "Enviar conjunto de alterações atual para o Mapillary"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "Enviar Conjunto de Alterações Mapillary"
+
+msgid "Submitting changeset to server…"
+msgstr "A enviar o conjunto de alterações para o servidor..."
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Formatos de imagem suportados (JPG e PNG)"
+
+msgid "Tag conflict"
+msgstr "Conflito de etiquetas"
+
+msgid "There are currently no layers with geotagged images!"
+msgstr "Não existem neste momento camadas com imagens geo-referenciadas!"
+
+msgid "Too many map objects, zoom in to see all."
+msgstr "Demasiados objetos, aproxime para os ver a todos."
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Total de imagens Mapillary: {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "Virada {0} imagem"
+msgstr[1] "Viradas {0} imagens"
+
+msgid "Undo"
+msgstr "Desfazer"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Lomba"
+
+msgid "Update"
+msgstr "Atualizar"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "A enviar: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "Usar formato 24 horas"
+
+msgid "User"
+msgstr "Utilizador"
+
+msgid "View in browser"
+msgstr "Ver no navegador"
+
+msgid "Wait for full quality pictures"
+msgstr "Esperar pelas imagens em alta qualidade"
+
+msgid "Walk mode"
+msgstr "Modo a pé"
+
+#. i18n: Checkbox label in JOSM settings
+msgid ""
+"When opening Mapillary image in web browser, show the blur editor instead of"
+" the image viewer"
+msgstr ""
+"Ao abrir a imagem Mapillary no navegador de Internet, mostrar o editor de "
+"desfocagem em vez do visualizador de imagens"
+
+msgid "Which image layers do you want to import into the Mapillary layer?"
+msgstr "Que camadas de imagens quer importar para a camada Mapillary?"
+
+msgid "Years"
+msgstr "Anos"
+
+msgid "You are currently not logged in."
+msgstr "Neste momento não está autenticado."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "Está autenticado como ''{0}''."
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr ""
+"Não está autenticado, por favor entre na sua conta do Mapillary nas "
+"preferências"
+
+#, java-format
+msgid "You have successfully uploaded {0} images to mapillary.com"
+msgstr "Enviou com sucesso {0} imagens para mapillary.com"
+
+msgid "Zoom to selected image"
+msgstr "Aproximar a imagem selecionada"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Ver de perto a imagem Mapillary atualmente selecionada"
+
+msgid "approved"
+msgstr "aprovado"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "áreas com dados descarregados do OSM"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "tudo na área visível"
+
+msgid "image has no key"
+msgstr "A imagem não tem chave"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "apenas quando pedido manualmente"
+
+msgid "pending"
+msgstr "pendente"
+
+msgid "rejected"
+msgstr "regeitado"
+
+msgid "sequence has no key"
+msgstr "a sequência não tem chave"
+
+msgid "unknown user"
+msgstr "utilizador desconhecido"
+
+#, java-format
+msgid ""
+"{0}\n"
+"Could not read map objects from URL\n"
+"{1}!"
+msgstr ""
+"{0}\n"
+"Não foi possível ler os objetos do mapa do URL\n"
+"{1}!"
+
+#. i18n: {0} is the layer name, {1} the number of images in it
+#, java-format
+msgid "{0} ({1} images)"
+msgstr "{0} ({1} imagens)"
+
+#, java-format
+msgid "{0} detections"
+msgstr "{0} deteções"
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "{0} imagens descarregadas"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "{0} de imagens no total"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{0} imagens em {1} sequências"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr ""
+"{0} imagens submetidas, Chave do Conjunto de Alterações: {1}, Estado: {2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "{0} imagens importadas"
+
+#, java-format
+msgid "{0} sequences, each containing between {1} and {2} images (ø {3})"
+msgstr "{0} sequências, cada uma contendo entre {1} e {2} imagens (ø {3})"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr ""
+"Permite usar fotografias geo-referenciadas ao nível da rua do site "
+"mapillary.com; Depois de instalado este módulo, está disponível o menu "
+"Imagens de Fundo>Mapillary, que adiciona uma camada \"Mapillary\" e abre um "
+"painel lateral direito mostrando fotografias tiradas por utilizadores do "
+"mapillary.com das ruas e locais em geral para ajudar a mapear. Notar que as "
+"fotografias e os ícones e linhas do percurso na área de desenho podem "
+"demorar alguns segundos a aparecer (são carregadas automaticamente tal como "
+"as imagens de satélite do Bing). Caso não apareça nada na camada Mapillary é"
+" porque ainda ninguém tirou fotografias nesse local."
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/pt_BR.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/pt_BR.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/pt_BR.po	(revision 34317)
@@ -0,0 +1,442 @@
+# Translations for the JOSM plugin 'Mapillary' (pt_BR)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: floscher, 2018\n"
+"Language-Team: Portuguese (Brazil) (https://www.transifex.com/josm/teams/2544/pt_BR/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: pt_BR\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+msgid "2 images joined"
+msgstr "2 imagens se juntaram"
+
+msgid "2 images unjoined"
+msgstr "2 imagens se separaram"
+
+msgid ""
+"An exception occured while trying to submit a changeset. If this happens "
+"repeatedly, consider reporting a bug via the Help menu. If this message "
+"appears for the first time, simply try it again. This might have been an "
+"issue with the internet connection."
+msgstr ""
+"Ocorreu um problema ao tentar enviar o conjunto de alterações. Se isto "
+"acontecer repetidamente, considere reportar o erro a partir do menu Ajuda. "
+"Se esta mensagem apareceu pela primeira vez, basta tentar novamente. Isso "
+"pode ser um problema na conexão com a internet."
+
+msgid "Cancel"
+msgstr "Cancelar"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr "O envio do Conjunto de Alterações falhou com {0} erro ''{1} {2}''!"
+
+msgid "Choose signs"
+msgstr "Escolha placas"
+
+msgid "Continues with the paused walk."
+msgstr "Continua com a caminhada pausada."
+
+msgid "Current Mapillary changeset"
+msgstr "Conjunto de Alterações Mapillary atual"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Cut off sequences at download bounds"
+msgstr "Cortar as sequências de acordo com os limites de download"
+
+msgid "Days"
+msgstr "Dias"
+
+msgid "Delete after upload"
+msgstr "Excluir após o upload"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "Apagar {0} imagem"
+msgstr[1] "Apagar {0} imagens"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Mostra hora quando a foto foi tirada"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr "Mostra a camada do mapa de objetos detectados pela Mapillary"
+
+msgid "Download Mapillary images in current view"
+msgstr "Obtendo imagens do Mapillary na visão atual"
+
+msgid "Download mode"
+msgstr "Modo de download"
+
+msgid "Downloaded images"
+msgstr "Imagens baixadas"
+
+msgid "Downloading"
+msgstr "Baixando"
+
+msgid "Downloading Mapillary images"
+msgstr "Baixar imagens do Mapillary"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr "Ativar funcionalidades beta e experimentais (pode ser instável)"
+
+msgid "Explore"
+msgstr "Explorar"
+
+msgid "Export Mapillary images"
+msgstr "Exportar imagens Mapillary"
+
+msgid "Export all images"
+msgstr "Exportar todas as imagens"
+
+msgid "Export selected images"
+msgstr "Exportação imagens selecionadas"
+
+msgid "Export selected sequence"
+msgstr "Exportar sequência selecionada"
+
+msgid "Finished upload"
+msgstr "Upload terminado"
+
+msgid "Follow selected image"
+msgstr "Seguir imagem selecionada"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Dê a preferência"
+
+msgid "Go forward"
+msgstr "Ir para a frente"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr ""
+"Vá para configuração e faça login no Mapillary antes de fazer o upload."
+
+msgid "Import"
+msgstr "Importar"
+
+msgid "Import local pictures"
+msgstr "Importar imagens locais"
+
+msgid "Import pictures"
+msgstr "Importar imagens"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Importar imagens na camada do Mapillary"
+
+msgid "Imported images"
+msgstr "Imagens importadas"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "Importar {0} imagem"
+msgstr[1] "Importar {0} imagens"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Cruzamento perigoso"
+
+msgid "Join mode"
+msgstr "Join mode"
+
+msgid "Join/unjoin pictures"
+msgstr "Juntar/Desunir imagens"
+
+msgid "Jump to blue"
+msgstr "Ir para azul"
+
+msgid "Jump to red"
+msgstr "Ir para vermelho"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Pula para a foto no outro lado da linha azul"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Pula para a foto no outro lado da linha vermelha"
+
+msgid "Login"
+msgstr "Login"
+
+msgid "Login successful, return to JOSM."
+msgstr "Login bem sucedido, retornar ao JOSM."
+
+msgid "Logout"
+msgstr "Logout"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Sentido obrigatório (qualquer)"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Mapillary Imagens"
+
+msgid "Mapillary changeset"
+msgstr "Conjunto de alterações Mapillary"
+
+msgid "Mapillary filter"
+msgstr "Mapillary filtro"
+
+msgid "Mapillary history"
+msgstr "Mapillary história"
+
+msgid "Mapillary image"
+msgstr "Imagem Mapillary"
+
+msgid "Mapillary layer"
+msgstr "Mapillary camada"
+
+msgid "Mapillary login"
+msgstr "Mapillary login"
+
+msgid "Mapillary object layer"
+msgstr "Camada de objetos do Mapillary"
+
+msgid "Months"
+msgstr "Meses"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr "Move para a localização de fotos com os botões próximo/anterior"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "Movida {0} imagem"
+msgstr[1] "Movidas {0} imagens"
+
+msgid "Next picture"
+msgstr "Próxima foto"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "Entrada proibida"
+
+msgid "No image selected"
+msgstr "Nenhuma imagem selecionada"
+
+msgid "No images found"
+msgstr "Nenhuma imagem encontrada"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "Proibido ultrapassar"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "Proibido estacionar"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "Proibido virar"
+
+msgid "Not older than: "
+msgstr "Não mais velho do que: "
+
+msgid "Only images with signs"
+msgstr "Somente imagens com placas"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Abrir caixa de diálogo do conjunto de alterações Mapillary"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Abrir filtro Mapillary"
+
+msgid "Open Mapillary history dialog"
+msgstr "Abrir histórico Mapillary"
+
+msgid "Open Mapillary layer"
+msgstr "Abrir camada Mapillary"
+
+msgid "Open Mapillary window"
+msgstr "Abrir janela Mapillary"
+
+msgid "Pause"
+msgstr "Pausar"
+
+msgid "Pauses the walk."
+msgstr "Pausa a caminhada."
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Travessia de pedestres"
+
+msgid "Play"
+msgstr "Tocar"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "Pressione \"{0}\" para baixar as imagens"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Pré-visualizar imagens ao passar o mouse sobre o ícone"
+
+msgid "Previous picture"
+msgstr "Foto anterior"
+
+msgid "Redo"
+msgstr "Refazer"
+
+msgid "Reset"
+msgstr "Reiniciar"
+
+msgid "Rewrite imported images"
+msgstr "Reescreve imagens importadas"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Rotatória"
+
+msgid "Select a directory"
+msgstr "Selecione um diretório"
+
+msgid "Select mode"
+msgstr "Modo de seleção"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Mostra a próxima foto na sequência"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Mostra a foto anterior na sequência"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Limite de velocidade"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Pare"
+
+msgid "Stops the walk."
+msgstr "Para a caminhada."
+
+msgid "Submit changeset"
+msgstr "Enviar o conjunto de alterações"
+
+msgid "Submit the current changeset"
+msgstr "Enviar o conjunto de alterações atual"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "Enviar o conjunto de alterações atual para a Mapillary"
+
+msgid "Submitting changeset to server…"
+msgstr "Enviando conjunto de alterações para o servidor..."
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Formatos de imagens suportado (JPG e PNG)"
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Total de imagens Mapillary: {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "Virada {0} imagem"
+msgstr[1] "Viradas {0} imagens"
+
+msgid "Undo"
+msgstr "Desfazer"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Estrada irregular"
+
+msgid "Update"
+msgstr "Atualizar"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Enviando: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "Usar formato de 24 horas"
+
+msgid "User"
+msgstr "Usuário"
+
+msgid "Wait for full quality pictures"
+msgstr "Espere por imagens de qualidade total"
+
+msgid "Walk mode"
+msgstr "Modo caminhada"
+
+#. i18n: Checkbox label in JOSM settings
+msgid ""
+"When opening Mapillary image in web browser, show the blur editor instead of"
+" the image viewer"
+msgstr ""
+"Ao abrir a imagem Mapillary no navegador da web, mostrar o editor de "
+"desfocagem ao invés do visualizador de imagens"
+
+msgid "Years"
+msgstr "Anos"
+
+msgid "You are currently not logged in."
+msgstr "No momento você não está logado."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "Você está logado como ''{0}''."
+
+msgid "Zoom to selected image"
+msgstr "Zoom para a imagem selecionada"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Zoom para a imagem selecionada no Mapillary no momento"
+
+msgid "approved"
+msgstr "aprovado"
+
+msgid "pending"
+msgstr "pendente"
+
+msgid "rejected"
+msgstr "rejeitado"
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "{0} imagens baixadas"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "{0} imagens no total"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{0} imagens em {1} sequências"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr ""
+"{0} imagens enviadas, chave do Conjunto de Alterações: {1}, Estado: {2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "{0} imagens importadas"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr "Permite o usuário trabalhar com imagens hospedadas em mapillary.com"
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/ru.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/ru.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/ru.po	(revision 34317)
@@ -0,0 +1,674 @@
+# Translations for the JOSM plugin 'Mapillary' (ru)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Nikolay Parukhin <parukhin@gmail.com>, 2018\n"
+"Language-Team: Russian (https://www.transifex.com/josm/teams/2544/ru/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ru\n"
+"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
+
+msgid "2 images joined"
+msgstr "2 снимка соединены"
+
+msgid "2 images unjoined"
+msgstr "2 снимка разъединены"
+
+#, java-format
+msgid ""
+"A tag with key <i>{0}</i> is already present on the selected OSM object."
+msgstr "Тег с ключом <i>{0}</i> уже есть у выделенного объекта OSM."
+
+msgid "Add Mapillary tag"
+msgstr "Добавить тег Mapillary"
+
+msgid "All images in a directory"
+msgstr "Все изображения в каталоге"
+
+msgid "All map objects loaded."
+msgstr "Все объекты карты загружены."
+
+msgid ""
+"An exception occured while trying to submit a changeset. If this happens "
+"repeatedly, consider reporting a bug via the Help menu. If this message "
+"appears for the first time, simply try it again. This might have been an "
+"issue with the internet connection."
+msgstr ""
+"Произошла ошибка при попытке отправить пакет правок на сервер. Если она "
+"возникает периодически, можете отправить отчёт об ошибке через меню Справка."
+" Если это сообщение появилось впервые, просто попробуйте ещё раз: возможно "
+"это была проблема с подключением к Интернету."
+
+msgid "Cancel"
+msgstr "Отмена"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr ""
+"Не удалось отправить пакет правок по версии протокола {0} с ошибкой: ''{1} "
+"{2}''!"
+
+msgid "Choose signs"
+msgstr "Выберите знаки"
+
+msgid "Continues with the paused walk."
+msgstr "Продолжить приостановленную прогулку"
+
+msgid "Copy key"
+msgstr "Копировать ID"
+
+msgid "Could not import a geotagged image to the Mapillary layer!"
+msgstr "Не удалось импортировать геотегированный снимок в слой Mapillary!"
+
+#, java-format
+msgid "Could not import the directory ''{0}''!"
+msgstr "Не удалось импортировать каталог ''{0}''!"
+
+#, java-format
+msgid "Could not import the image ''{0}''!"
+msgstr "Не удалось импортировать изображение ''{0}''!"
+
+#, java-format
+msgid "Could not open the URL {0} in a browser"
+msgstr "Не удалось открыть URL {0} в браузере"
+
+#, java-format
+msgid "Could not read from URL {0}!"
+msgstr "Не удалось выполнить чтение из URL {0}!"
+
+msgid "Current Mapillary changeset"
+msgstr "Текущий  пакет правок Mapillary"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Cut off sequences at download bounds"
+msgstr "Обрезать последовательности по границам скачанной области"
+
+msgid "Days"
+msgstr "дней"
+
+msgid "Delete after upload"
+msgstr "Удалить после отправки"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "Удалён {0} снимок"
+msgstr[1] "Удалены {0} снимка"
+msgstr[2] "Удалено {0} снимков"
+msgstr[3] "Удалено {0} снимка"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Показывать время, когда был сделан снимок"
+
+msgid "Displays detail information on the currently selected Mapillary image"
+msgstr "Показывает подробную информацию о текущем выделенном снимке Mapillary"
+
+msgid "Displays objects detected by Mapillary from their street view imagery"
+msgstr "Отображает объекты, обнаруженные Mapillary в своих снимках улиц"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr "Отображает слой с объектами карты, обнаруженными Mapillary"
+
+#, java-format
+msgid ""
+"Do you really want to replace the current value <i>{0}</i> with the new "
+"value <i>{1}</i>?"
+msgstr ""
+"Вы действительно хотите заменить текущее значение <i>{0}</i> на новое "
+"значение <i>{1}</i>?"
+
+msgid "Download Mapillary images in current view"
+msgstr "Скачать снимки Mapillary в текущей области"
+
+msgid "Download mode"
+msgstr "Режим скачивания"
+
+msgid "Downloaded images"
+msgstr "Скачанные снимки"
+
+msgid "Downloading"
+msgstr "Загрузка"
+
+msgid "Downloading Mapillary images"
+msgstr "Скачивание снимков Mapillary"
+
+msgid "Downloading map objects failed!"
+msgstr "Не удалось скачать объекты карты!"
+
+msgid "Downloading map objects…"
+msgstr "Скачивание объектов карты…"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr "Включить экспериментальные функции (могут быть нестабильными)"
+
+msgid "Explore"
+msgstr "Обзор"
+
+msgid "Export Mapillary images"
+msgstr "Экспортировать снимки Mapillary"
+
+msgid "Export all images"
+msgstr "Экспортировать все снимки"
+
+msgid "Export selected images"
+msgstr "Экспортировать выбранные снимки"
+
+msgid "Export selected sequence"
+msgstr "Экспортировать выбранную последовательность"
+
+msgid "Exporting Mapillary Images"
+msgstr "Экспорт снимков Mapillary"
+
+msgid "Finished upload"
+msgstr "Отправка завершена"
+
+msgid "Follow selected image"
+msgstr "Следовать за выделенным снимком"
+
+msgid "From existing image layer"
+msgstr "Из существующего слоя изображений"
+
+msgid "From which source do you want to import images to the Mapillary layer?"
+msgstr ""
+"Из какого источника вы хотите импортировать изображения в слой Mapillary?"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Уступите дорогу"
+
+msgid "Go forward"
+msgstr "Вперёд"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr "Перейти к настройкам и войти в Mapillary перед отправкой данных."
+
+msgid "I got it, close this."
+msgstr "Понятно, закрыть окно."
+
+msgid "Image actions"
+msgstr "Действия со снимком"
+
+msgid "Image detections"
+msgstr "Обнаружение знаков"
+
+msgid "Image info"
+msgstr "Информация о снимке"
+
+msgid "Image key"
+msgstr "Идентификатор снимка"
+
+msgid "Images from my file system"
+msgstr "Изображения из моей файловой системы"
+
+msgid "Import"
+msgstr "Импортировать"
+
+msgid "Import exception"
+msgstr "Ошибка импорта"
+
+msgid "Import local pictures"
+msgstr "Импортировать локальные изображения"
+
+msgid "Import pictures"
+msgstr "Импортировать изображения"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Импортировать изображения на слой Mapillary"
+
+msgid "Imported images"
+msgstr "Импортированные изображения"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "Импортирован {0} снимок"
+msgstr[1] "Импортированы {0} снимка"
+msgstr[2] "Импортировано {0} снимков"
+msgstr[3] "Импортировано {0} снимка"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Пересечение со второстепенной"
+
+msgid ""
+"It can be activated by clicking the left button at the bottom of this "
+"message or the button in the toolbar on the left, which uses the same icon."
+msgstr ""
+"Её можно активировать щелчком левой кнопкой внизу этого сообщения или "
+"кнопкой с тем же значком в панели инструментов слева."
+
+msgid "Join mode"
+msgstr "Режим объединения"
+
+msgid "Join/unjoin pictures"
+msgstr "Соединить/разъединить снимки"
+
+msgid "Jump to blue"
+msgstr "Перейти к синему"
+
+msgid "Jump to red"
+msgstr "Перейти к красному"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Перейти к изображению на другой стороне синей линии"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Перейти к изображению на другой стороне красной линии"
+
+msgid "Key copied to clipboard"
+msgstr "Ключ скопирован в буфер обмена"
+
+msgid "Login"
+msgstr "Войти"
+
+msgid "Login successful, return to JOSM."
+msgstr "Вход успешно выполнен, возврат в JOSM."
+
+msgid "Logout"
+msgstr "Выйти"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Предписываемое направление движения (любое)"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Изображения Mapillary"
+
+msgid "Mapillary changeset"
+msgstr "Пакет правок Mapillary"
+
+msgid "Mapillary filter"
+msgstr "Фильтр Mapillary"
+
+msgid "Mapillary history"
+msgstr "История Mapillary"
+
+msgid "Mapillary image"
+msgstr "Снимок Mapillary"
+
+msgid "Mapillary layer"
+msgstr "Слой Mapillary"
+
+msgid "Mapillary login"
+msgstr "Вход в Mapillary"
+
+msgid "Mapillary object layer"
+msgstr "Слой объектов Mapillary"
+
+msgid "Mapillary objects"
+msgstr "Объекты Mapillary"
+
+msgid "Months"
+msgstr "месяцев"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr ""
+"Перемещаться к местоположению снимка по кнопкам ''Предыдущий/Следующий "
+"снимок''"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "Перемещён {0} снимок"
+msgstr[1] "Перемещены {0} снимка"
+msgstr[2] "Перемещено {0} снимков"
+msgstr[3] "Перемещено {0} снимка"
+
+msgid "Next picture"
+msgstr "Следующий снимок"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "Въезд запрещён"
+
+msgid "No image selected"
+msgstr "Изображение не выбрано"
+
+msgid "No images found"
+msgstr "Изображения не найдены"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "Обгон запрещён"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "Остановка запрещена"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "Поворот запрещён"
+
+msgid "Not Logged in to Mapillary"
+msgstr "Не выполнен вход в Mapillary"
+
+msgid "Not older than: "
+msgstr "Не старее: "
+
+#. i18n: Spinner label in JOSM settings
+msgid "Number of images to be pre-fetched (forwards and backwards)"
+msgstr "Количество снимков для упреждающей загрузки (вперёд и назад)"
+
+msgid "Only images with signs"
+msgstr "Только изображения со знаками"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Открыть диалог пакета правок Mapillary"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Открыть диалог фильтра Mapillary"
+
+msgid "Open Mapillary history dialog"
+msgstr "Открыть диалог истории Mapillary"
+
+msgid "Open Mapillary layer"
+msgstr "Открыть слой Mapillary"
+
+msgid "Open Mapillary window"
+msgstr "Открыть окно Mapillary"
+
+msgid "Pause"
+msgstr "Пауза"
+
+msgid "Pauses the walk."
+msgstr "Приостановить прогулку"
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Пешеходный переход"
+
+msgid "Play"
+msgstr "Пуск"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "Нажмите \"{0}\" для скачивания изображений"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Предпросмотр изображения при наведении на его значок"
+
+msgid "Previous picture"
+msgstr "Предыдущий снимок"
+
+msgid "Redo"
+msgstr "Вернуть"
+
+msgid "Reset"
+msgstr "Сброс"
+
+msgid "Rewrite imported images"
+msgstr "Перезаписать импортированные изображения"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Круг"
+
+msgid "Select a directory"
+msgstr "Выберите каталог"
+
+msgid "Select directory to import images from"
+msgstr "Выберите каталог для импорта изображений"
+
+msgid "Select mode"
+msgstr "Режим выделения"
+
+msgid "Select the images you want to import"
+msgstr "Выберите изображения, которые вы хотите импортировать"
+
+msgid "Sequence key"
+msgstr "Идентификатор последовательности"
+
+msgid "Show detections on top of image"
+msgstr "Показывать обнаруженные поверх снимка"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Показать следующее изображение в последовательности"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Показать предыдущее изображение в последовательности"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Ограничение скорости"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Стоп"
+
+msgid "Stops the walk."
+msgstr "Остановить прогулку"
+
+msgid "Submit changeset"
+msgstr "Передать пакет правок"
+
+msgid "Submit the current changeset"
+msgstr "Передать текущий пакет правок"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "Передать текущий  пакет правок в Mapillary"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "Передача пакета правок Mapillary"
+
+msgid "Submitting changeset to server…"
+msgstr "Отправка пакета правок на сервер…"
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Поддерживаемые форматы изображений (JPG и PNG)"
+
+msgid "Tag conflict"
+msgstr "Конфликт тегов"
+
+msgid ""
+"The Mapillary layer has stopped downloading images, because the requested "
+"area is too big!"
+msgstr ""
+"Остановлено скачивание снимков на слой Mapillary, так как запрошенная "
+"область слишком велика!"
+
+msgid ""
+"The Mapillary plugin now uses a separate panel to display extra information "
+"(like the image key) and actions for the currently selected Mapillary image "
+"(like viewing it in a browser)."
+msgstr ""
+"Модуль Mapillary теперь использует отдельную панель для показа "
+"дополнительной информации (типа идентификатора снимка) и действий для "
+"текущего выделенного снимка Mapillary (например, просмотра его в браузере)."
+
+msgid "There are currently no layers with geotagged images!"
+msgstr "Нет слоёв с геопривязанными изображениями!"
+
+#, java-format
+msgid ""
+"To solve this problem, you could switch to download mode ''{0}'' and load "
+"Mapillary images for a smaller portion of the map."
+msgstr ""
+"Для решения этой проблемы можно переключиться в режим загрузки ''{0}'' и "
+"скачать снимки Mapillary для меньшей части карты."
+
+msgid ""
+"To solve this problem, you could zoom in and load a smaller area of the map."
+msgstr ""
+"Для решения этой проблемы можно увеличить масштаб и скачать меньшую область "
+"карты."
+
+msgid "Too many map objects, zoom in to see all."
+msgstr "Слишком много объектов на карте. Приблизьте, чтобы увидеть все."
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Всего снимков Mapillary: {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "Повёрнут {0} снимок"
+msgstr[1] "Повёрнуты {0} снимка"
+msgstr[2] "Повёрнуто {0} снимков"
+msgstr[3] "Повёрнуто {0} снимка"
+
+msgid "Undo"
+msgstr "Отмена"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Неровная дорога"
+
+msgid "Update"
+msgstr "Обновить"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Отправка: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "Использовать 24-часовой формат"
+
+msgid "User"
+msgstr "Пользователь"
+
+msgid "View in browser"
+msgstr "Открыть в браузере"
+
+msgid "Wait for full quality pictures"
+msgstr "Ждать загрузки снимков в полном разрешении"
+
+msgid "Walk mode"
+msgstr "Режим прогулки"
+
+#. i18n: Checkbox label in JOSM settings
+msgid ""
+"When opening Mapillary image in web browser, show the blur editor instead of"
+" the image viewer"
+msgstr ""
+"При открытии снимка Mapillary в браузере показывать редактор размытий вместо"
+" просмотра снимка"
+
+msgid "Which image layers do you want to import into the Mapillary layer?"
+msgstr "Какие слои с изображениями вы хотите импортировать в слой Mapillary?"
+
+msgid "Years"
+msgstr "лет"
+
+msgid "You are currently not logged in."
+msgstr "Вы не выполнили вход."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "Вы вошли как ''{0}''."
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr "Не выполнен вход, войдите в Mapillary в Настройках"
+
+#, java-format
+msgid "You have successfully uploaded {0} images to mapillary.com"
+msgstr "Вы успешно загрузили {0} изображений на mapillary.com"
+
+msgid "Zoom to selected image"
+msgstr "Масштабировать до выбранного снимка"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Приблизить вид до текущего выбранного снимка Mapillary"
+
+msgid "approved"
+msgstr "принят"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "области со скачанными данными OSM"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "всё в видимой области"
+
+msgid "image has no key"
+msgstr "у снимка нет идентификатора"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "только при запросе вручную"
+
+msgid "pending"
+msgstr "в ожидании"
+
+msgid "rejected"
+msgstr "отклонён"
+
+msgid "sequence has no key"
+msgstr "у последовательности нет идентификатора"
+
+msgid "unknown user"
+msgstr "неизвестный пользователь"
+
+#, java-format
+msgid ""
+"{0}\n"
+"Could not read map objects from URL\n"
+"{1}!"
+msgstr ""
+"{0}\n"
+"Не удалось прочитать объекты карты из URL\n"
+"{1}!"
+
+#. i18n: {0} is the layer name, {1} the number of images in it
+#, java-format
+msgid "{0} ({1} images)"
+msgstr "{0} ({1} снимков)"
+
+#, java-format
+msgid "{0} detections"
+msgstr "Обнаружено: {0}"
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "{0} скачанных снимков"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "{0} снимков всего"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{0} снимков в {1} последовательностях"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr ""
+"{0} снимков отправлено, идентификатор пакета правок: {1}, состояние: {2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "{0} импортированных снимков"
+
+#, java-format
+msgid "{0} sequences, each containing between {1} and {2} images (ø {3})"
+msgstr ""
+"{0} последовательностей, каждая содержит от {1} до {2} снимков (ø {3})"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr ""
+"Позволяет пользователям работать с изображениями, размещёнными на "
+"mapillary.com"
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/sk.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/sk.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/sk.po	(revision 34317)
@@ -0,0 +1,654 @@
+# Translations for the JOSM plugin 'Mapillary' (sk)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: floscher, 2018\n"
+"Language-Team: Slovak (https://www.transifex.com/josm/teams/2544/sk/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: sk\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+msgid "2 images joined"
+msgstr "2 obrázky spojené"
+
+msgid "2 images unjoined"
+msgstr "2 obrázky rozpojené"
+
+#, java-format
+msgid ""
+"A tag with key <i>{0}</i> is already present on the selected OSM object."
+msgstr "Značka s kľúčom <i>{0}</i> už na zvolenom OSM objekte existuje."
+
+msgid "Add Mapillary tag"
+msgstr "Pridať značku Mapillary"
+
+msgid "All images in a directory"
+msgstr "Všetky obrázky v priečinku"
+
+msgid "All map objects loaded."
+msgstr "Všetky mapové objekty stiahnuté."
+
+msgid ""
+"An exception occured while trying to submit a changeset. If this happens "
+"repeatedly, consider reporting a bug via the Help menu. If this message "
+"appears for the first time, simply try it again. This might have been an "
+"issue with the internet connection."
+msgstr ""
+"Pri odosielaní sady zmien nastala výnimka. Ak sa to opakuje, zvážte "
+"nahlásenie chyby cez menu Pomocník. Ak sa táto správa zobrazila prvýkrát, "
+"skúste odoslanie znovu. Mohol to byť dočasný problém s pripojením na "
+"Internet."
+
+msgid "Cancel"
+msgstr "Zrušiť"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr "Odoslanie sady zmien zlyhalo s {0} chybou \"{1} {2}\"!"
+
+msgid "Choose signs"
+msgstr "Zvoľte značky"
+
+msgid "Continues with the paused walk."
+msgstr "Pokračuje v pozastavenej chôdzi."
+
+msgid "Copy key"
+msgstr "Kopírovať kľúč"
+
+msgid "Could not import a geotagged image to the Mapillary layer!"
+msgstr ""
+"Nepodarilo sa importovať obrázok s geografickou polohou do vrstvy Mapillary!"
+
+#, java-format
+msgid "Could not import the directory ''{0}''!"
+msgstr "Nepodarilo sa importovať priečinok \"{0}\"!"
+
+#, java-format
+msgid "Could not import the image ''{0}''!"
+msgstr "Nepodarilo sa importovať obrázok \"{0}\"!"
+
+#, java-format
+msgid "Could not open the URL {0} in a browser"
+msgstr "Nepodarilo sa otvoriť adresu {0} v prehliadači"
+
+#, java-format
+msgid "Could not read from URL {0}!"
+msgstr "Nepodarilo sa čítať z adresy {0}!"
+
+msgid "Current Mapillary changeset"
+msgstr "Aktuálna sada zmien Mapillary"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Cut off sequences at download bounds"
+msgstr "Odseknúť postupnosť na hranici stiahnutej oblasti"
+
+msgid "Days"
+msgstr "Dní"
+
+msgid "Delete after upload"
+msgstr "Vymazať po odoslaní"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "{0} obrázkov vymazaných"
+msgstr[1] "{0} obrázok vymazaný"
+msgstr[2] "{0} obrázky vymazané"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Zobraziť hodinu kedy bol obrázok zaznamenaný"
+
+msgid "Displays detail information on the currently selected Mapillary image"
+msgstr "Zobrazí detaily o práve zvolenom obrázku Mapillary"
+
+msgid "Displays objects detected by Mapillary from their street view imagery"
+msgstr "Zobrazí objekty detegované Mapillary z obrázkov ulíc"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr "Zobrazí vrstvu s mapovými objektami, ktoré identifikoval Mapillary"
+
+#, java-format
+msgid ""
+"Do you really want to replace the current value <i>{0}</i> with the new "
+"value <i>{1}</i>?"
+msgstr ""
+"Naozaj chcete nahradiť existujúcu hodnotu <i>{0}</i> novou hodnotou "
+"<i>{1}</i>?"
+
+msgid "Download Mapillary images in current view"
+msgstr "Stiahnuť obrázky z Mapillary pre aktuálny pohľad"
+
+msgid "Download mode"
+msgstr "Režim sťahovania"
+
+msgid "Downloaded images"
+msgstr "Stiahnuté obrázky"
+
+msgid "Downloading"
+msgstr "Sťahuje sa"
+
+msgid "Downloading Mapillary images"
+msgstr "Sťahujú sa obrázky Mapillary"
+
+msgid "Downloading map objects failed!"
+msgstr "Sťahovanie mapových objektov zlyhalo!"
+
+msgid "Downloading map objects…"
+msgstr "Sťahujú sa mapové objekty…"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr "Zapnúť experimentálne vyvíjané funkcie (môžu byť nestabilné)"
+
+msgid "Explore"
+msgstr "Preskúmať"
+
+msgid "Export all images"
+msgstr "Exportovať všetky obrázky"
+
+msgid "Export selected images"
+msgstr "Exportovať vybrané obrázky"
+
+msgid "Export selected sequence"
+msgstr "Exportovať vybranú postupnosť"
+
+msgid "Finished upload"
+msgstr "Odoslanie ukončené"
+
+msgid "Follow selected image"
+msgstr "Nasledovať vybraný obrázok"
+
+msgid "From existing image layer"
+msgstr "Z existujúcej vrstvy obrázkov"
+
+msgid "From which source do you want to import images to the Mapillary layer?"
+msgstr "Z akého zdroja chcete importovať obrázky do vrstvy Mapillary?"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Daj prednosť v jazde"
+
+msgid "Go forward"
+msgstr "Prejsť dopredu"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr "Pred odosielaním choďte do nastavení a prihláste sa do Mapillary."
+
+msgid "I got it, close this."
+msgstr "Pochopil som, zavrieť."
+
+msgid "Image actions"
+msgstr "Akcie s obrázkom"
+
+msgid "Image detections"
+msgstr "Objekty detekované v obrázku"
+
+msgid "Image info"
+msgstr "Informácie o obrázku"
+
+msgid "Image key"
+msgstr "Kľúč obrázku"
+
+msgid "Images from my file system"
+msgstr "Obrázky z disku"
+
+msgid "Import"
+msgstr "Importovať"
+
+msgid "Import exception"
+msgstr "Výnimka pri importe"
+
+msgid "Import local pictures"
+msgstr "Importovať lokálne obrázky"
+
+msgid "Import pictures"
+msgstr "Importovať obrázky"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Importovať obrázky do vrstvy Mapillary"
+
+msgid "Imported images"
+msgstr "Importované obrázky"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "{0} obrázkov importovaných"
+msgstr[1] "{0} obrázok importovaný"
+msgstr[2] "{0} obrázky importované"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Pozor, križovatka"
+
+msgid ""
+"It can be activated by clicking the left button at the bottom of this "
+"message or the button in the toolbar on the left, which uses the same icon."
+msgstr ""
+"Môže byť aktivovaný kliknutím na ľavé tlačidlo naspodku tejto správy, alebo "
+"tlačidlo na paneli nástrojov vľavo, ktoré má rovnakú ikonu."
+
+msgid "Join mode"
+msgstr "Režim spájania"
+
+msgid "Join/unjoin pictures"
+msgstr "Spojiť/oddeliť obrázky"
+
+msgid "Jump to blue"
+msgstr "Skočiť na modrú"
+
+msgid "Jump to red"
+msgstr "Skočiť na červenú"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Preskočí na obrázok na druhej strane modrej čiary"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Preskočí na obrázok na druhej strane červenej čiary"
+
+msgid "Key copied to clipboard"
+msgstr "Kľúč skopírovaný do schránky"
+
+msgid "Login"
+msgstr "Prihlásiť sa"
+
+msgid "Login successful, return to JOSM."
+msgstr "Prihlásenie úspešné, vráťte sa do JOSM."
+
+msgid "Logout"
+msgstr "Odhlásiť sa"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Prikázaný smer jazdy"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Obrázky z Mapillary"
+
+msgid "Mapillary changeset"
+msgstr "Sada zmien Mapillary"
+
+msgid "Mapillary filter"
+msgstr "Filter Mapillary"
+
+msgid "Mapillary history"
+msgstr "História Mapillary"
+
+msgid "Mapillary layer"
+msgstr "Vrstva Mapillary"
+
+msgid "Mapillary login"
+msgstr "Prihlásenie do Mapillary"
+
+msgid "Mapillary object layer"
+msgstr "Mapillary - vrstva objektov"
+
+msgid "Mapillary objects"
+msgstr "Objekty Mapillary"
+
+msgid "Months"
+msgstr "Mesiacov"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr "Tlačidlom nasledujúci/predchádzajúci sa presunúť na pozíciu obrázka"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "{0} obrázkov presunutých"
+msgstr[1] "{0} obrázok presunutý"
+msgstr[2] "{0} obrázky presunuté"
+
+msgid "Next picture"
+msgstr "Nasledujúci obrázok"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "Zákaz vstupu"
+
+msgid "No image selected"
+msgstr "Nie je vybratý žiadny obrázok"
+
+msgid "No images found"
+msgstr "Nenašli sa žiadne obrázky"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "Zákaz predbiehania"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "Zákaz parkovania"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "Zákaz odbočenia"
+
+msgid "Not Logged in to Mapillary"
+msgstr "Neprihlásený do Mapillary"
+
+msgid "Not older than: "
+msgstr "Nie staršie ako: "
+
+#. i18n: Spinner label in JOSM settings
+msgid "Number of images to be pre-fetched (forwards and backwards)"
+msgstr "Počet obrázkov načítaných vopred (dopredu a dozadu)"
+
+msgid "Only images with signs"
+msgstr "Iba obrázky so značkami"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Otvoriť okno pre sady zmien Mapillary"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Otvoriť okno filtra Mapillary"
+
+msgid "Open Mapillary history dialog"
+msgstr "Otvoriť okno histórie Mapillary"
+
+msgid "Open Mapillary layer"
+msgstr "Otvoriť vrstvu Mapillary"
+
+msgid "Open Mapillary window"
+msgstr "Otvoriť okno Mapillary"
+
+msgid "Pause"
+msgstr "Pozastaviť"
+
+msgid "Pauses the walk."
+msgstr "Pozastaví chôdzu."
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Priechod pre chodcov"
+
+msgid "Play"
+msgstr "Prehrať"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "Stlačte \"{0}\" pre stiahnutie obrázkov"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Zobraziť náhľady obrázkov pri prejdení nad ich ikonou"
+
+msgid "Previous picture"
+msgstr "Predchádzajúci obrázok"
+
+msgid "Redo"
+msgstr "Opakovať"
+
+msgid "Reset"
+msgstr "Vynulovať (Reset)"
+
+msgid "Rewrite imported images"
+msgstr "Prepísať importované obrázky"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Kruhový objazd"
+
+msgid "Select a directory"
+msgstr "Vybrať priečinok"
+
+msgid "Select directory to import images from"
+msgstr "Zvoľte priečinok na importovanie obrázkov"
+
+msgid "Select mode"
+msgstr "Vyberte režim"
+
+msgid "Select the images you want to import"
+msgstr "Vyberte obrázky, ktoré chcete importovať"
+
+msgid "Sequence key"
+msgstr "Kľúč postupnosti"
+
+msgid "Show detections on top of image"
+msgstr "Zobraziť detekované objekty nad obrázkom"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Zobrazí nasledujúci obrázok v postupnosti"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Zobrazí predchádzajúci obrázok v postupnosti"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Rýchlostné obmedzenie"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Značka \"Zastaviť (stop)\""
+
+msgid "Stops the walk."
+msgstr "Zastaví chôdzu."
+
+msgid "Submit changeset"
+msgstr "Odoslať sadu zmien"
+
+msgid "Submit the current changeset"
+msgstr "Odoslať aktuálnu sadu zmien"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "Odoslať aktuálnu sadu zmien do Mapillary"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "Odosiela sa sada zmien Mapillary"
+
+msgid "Submitting changeset to server…"
+msgstr "Odosiela sa sada zmien na server…"
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Podporované formáty obrázkov (JPG a PNG)"
+
+msgid "Tag conflict"
+msgstr "Konflikt značiek"
+
+msgid ""
+"The Mapillary layer has stopped downloading images, because the requested "
+"area is too big!"
+msgstr ""
+"Vrstva Mapillary prestala sťahovať obrázky, pretože požadovaná oblasť je "
+"príliš veľká!"
+
+msgid ""
+"The Mapillary plugin now uses a separate panel to display extra information "
+"(like the image key) and actions for the currently selected Mapillary image "
+"(like viewing it in a browser)."
+msgstr ""
+"Plugin Mapillary teraz používa samostatný panel pre zobrazenie doplňujúcich "
+"informácií (ako kľúč obrázkov) a akcie pre zvolený obrázok Mapillary (napr. "
+"zobraziť v prehliadači)."
+
+msgid "There are currently no layers with geotagged images!"
+msgstr "Nemáte žiadne vrstvy s obrázkami s geografickou polohou!"
+
+#, java-format
+msgid ""
+"To solve this problem, you could switch to download mode ''{0}'' and load "
+"Mapillary images for a smaller portion of the map."
+msgstr ""
+"Na vyriešenie tohto problému môžete prepnúť režim sťahovania na \"{0}\" a "
+"načítajte obrázky Mapillary pre menšie oblasti mapy."
+
+msgid ""
+"To solve this problem, you could zoom in and load a smaller area of the map."
+msgstr ""
+"Na vyriešenie tohto problému môžete priblížiť zobrazenie a stiahnuť menšiu "
+"oblasť mapy."
+
+msgid "Too many map objects, zoom in to see all."
+msgstr ""
+"Príliš veľa mapových objektov. Priblížte oblasť, aby ste videli všetky."
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Spolu obrázkov Mapillary: {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "{0} obrázkov otočených"
+msgstr[1] "{0} obrázok otočený"
+msgstr[2] "{0} obrázky otočené"
+
+msgid "Undo"
+msgstr "Späť"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Nerovná cesta"
+
+msgid "Update"
+msgstr "Aktualizovať"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Odosiela sa: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "Použiť 24-hodinový formát"
+
+msgid "User"
+msgstr "Používateľ"
+
+msgid "View in browser"
+msgstr "Zobraziť v prehliadači"
+
+msgid "Wait for full quality pictures"
+msgstr "Čakať na obrázky v plnej kvalite"
+
+msgid "Walk mode"
+msgstr "Režim chôdze"
+
+#. i18n: Checkbox label in JOSM settings
+msgid ""
+"When opening Mapillary image in web browser, show the blur editor instead of"
+" the image viewer"
+msgstr ""
+"Keď je obrázok Mapillary otvorený vo webovom prehliadači, zobraziť editor "
+"rozmazania namiesto prehliadača obrázkov"
+
+msgid "Which image layers do you want to import into the Mapillary layer?"
+msgstr "Ktoré vrstvy obrázkov chcete importovať do vrstvy Mapillary?"
+
+msgid "Years"
+msgstr "Rokov"
+
+msgid "You are currently not logged in."
+msgstr "Nie ste prihlásený."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "Ste prihlásený ako \"{0}\"."
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr "Nie ste prihlásený, prosím prihláste sa do Mapillary v nastaveniach"
+
+#, java-format
+msgid "You have successfully uploaded {0} images to mapillary.com"
+msgstr "Úspešne ste odoslali {0} obrázkov na mapillary.com"
+
+msgid "Zoom to selected image"
+msgstr "Priblížiť na zvolený obrázok"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Priblížiť na zvolený obrázok z Mapillary"
+
+msgid "approved"
+msgstr "schválená"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "oblasti s už stiahnutými údajmi OSM"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "všetko vo viditeľnej oblasti"
+
+msgid "image has no key"
+msgstr "obrázok nemá kľúč"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "len keď je požadované"
+
+msgid "pending"
+msgstr "čakajúca"
+
+msgid "rejected"
+msgstr "odmietnutá"
+
+msgid "sequence has no key"
+msgstr "postupnosť nemá kľúč"
+
+msgid "unknown user"
+msgstr "neznámy používateľ"
+
+#, java-format
+msgid ""
+"{0}\n"
+"Could not read map objects from URL\n"
+"{1}!"
+msgstr ""
+"{0}\n"
+"Nepodarilo sa čítať mapové objekty z adresy\n"
+"{1}!"
+
+#. i18n: {0} is the layer name, {1} the number of images in it
+#, java-format
+msgid "{0} ({1} images)"
+msgstr "{0} ({1} obrázkov)"
+
+#, java-format
+msgid "{0} detections"
+msgstr "{0} detekovaných objektov"
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "{0} stiahnutých obrázkov"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "{0} obrázkov spolu"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{0} obrázkov v {1} postupnostiach"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr "{0} obrázkov odoslaných; kľúč sady zmien: {1}, stav: {2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "{0} importovaných obrázkov"
+
+#, java-format
+msgid "{0} sequences, each containing between {1} and {2} images (ø {3})"
+msgstr "{0} postupností, každá obsahuje medzi {1} a {2} obrázkov (ø {3})"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr "Umožňuje používateľovi pracovať s obrázkami na mapillary.com"
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/uk.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/uk.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/uk.po	(revision 34317)
@@ -0,0 +1,653 @@
+# Translations for the JOSM plugin 'Mapillary' (uk)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: floscher, 2018\n"
+"Language-Team: Ukrainian (https://www.transifex.com/josm/teams/2544/uk/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: uk\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+msgid "2 images joined"
+msgstr "2 зображення з’єднано"
+
+msgid "2 images unjoined"
+msgstr "2 зображення роз’єднано"
+
+#, java-format
+msgid ""
+"A tag with key <i>{0}</i> is already present on the selected OSM object."
+msgstr "Теґ з ключем <i>{0}</i> вже присутній у виділеного обʼєкта OSM."
+
+msgid "Add Mapillary tag"
+msgstr "Додати теґ Mapillary"
+
+msgid "All images in a directory"
+msgstr "Всі зображення у теці"
+
+msgid "All map objects loaded."
+msgstr "Всі обʼєкти мапи завантажено."
+
+msgid ""
+"An exception occured while trying to submit a changeset. If this happens "
+"repeatedly, consider reporting a bug via the Help menu. If this message "
+"appears for the first time, simply try it again. This might have been an "
+"issue with the internet connection."
+msgstr ""
+"Під час спроби надсилання набору змін на сервер виникла помилка. Якщо вона "
+"виникає періодично, сповістіть про неї, надіславши звіт про помилки (Див. в "
+"меню Довідка). Якщо це повідомлення зʼявилось вперше – спробуйте ще раз, "
+"можливо у вас виникла проблем з мережевим зʼєднанням."
+
+msgid "Cancel"
+msgstr "Скасувати"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr "Невдалось надісати набір змін, помилка  {0} ''{1} {2}''!"
+
+msgid "Choose signs"
+msgstr "Виберіть знаки"
+
+msgid "Continues with the paused walk."
+msgstr "Продовжує перегляд."
+
+msgid "Copy key"
+msgstr "Копіювати ключ"
+
+msgid "Could not import a geotagged image to the Mapillary layer!"
+msgstr "Неможливо імпортувати геотеговані знімки до шару Mapillary’!"
+
+#, java-format
+msgid "Could not import the directory ''{0}''!"
+msgstr "Неможливо імпортувати теку ''{0}''!"
+
+#, java-format
+msgid "Could not import the image ''{0}''!"
+msgstr "Неможливо імпортувати зображення ''{0}''!"
+
+#, java-format
+msgid "Could not open the URL {0} in a browser"
+msgstr "Не можливо відкрити URL {0} в оглядачі"
+
+#, java-format
+msgid "Could not read from URL {0}!"
+msgstr "Неможливо зчитати за посиланням URL {0}!"
+
+msgid "Current Mapillary changeset"
+msgstr "Поточний набір змін Mapillary"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Cut off sequences at download bounds"
+msgstr "Обмежити послідовність межами завантаженої ділянки"
+
+msgid "Days"
+msgstr "Дні"
+
+msgid "Delete after upload"
+msgstr "Вилучити післа надсиланання"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "Вилучений {0} знімок"
+msgstr[1] "Вилучено {0} знімки"
+msgstr[2] "Вилучено {0} знімків"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "Показувати час, коли було зроблено знімок"
+
+msgid "Displays detail information on the currently selected Mapillary image"
+msgstr "Показує докладну інформацію про поточний знімок Mapillary"
+
+msgid "Displays objects detected by Mapillary from their street view imagery"
+msgstr "Показує обʼєкти, які були виявлені Mapillary на їх знімках"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr "Показує шар з обʼєктами, що були виявлені Mapillary"
+
+#, java-format
+msgid ""
+"Do you really want to replace the current value <i>{0}</i> with the new "
+"value <i>{1}</i>?"
+msgstr ""
+"Ви дійсно бажаєете замінити поточне значення <i>{0}</i> на нове  <i>{1}</i>?"
+
+msgid "Download Mapillary images in current view"
+msgstr "Заватнажити знімки Mapillary для поточного виду"
+
+msgid "Download mode"
+msgstr "Режим завантаження"
+
+msgid "Downloaded images"
+msgstr "Завантажені знімки"
+
+msgid "Downloading"
+msgstr "Завантаження"
+
+msgid "Downloading Mapillary images"
+msgstr "Завантаження знімків Mapillary"
+
+msgid "Downloading map objects failed!"
+msgstr "Збій завантаження обʼєктів мапи!"
+
+msgid "Downloading map objects…"
+msgstr "Завантаження обʼєктів мапи…"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr "Увімкнути експериментальні бета-функції (можуть бути нестабільними)"
+
+msgid "Explore"
+msgstr "Оглянути"
+
+msgid "Export all images"
+msgstr "Експортувати всі знімки"
+
+msgid "Export selected images"
+msgstr "Експортувати виділені знімки"
+
+msgid "Export selected sequence"
+msgstr "Експортувати обрану послідовність"
+
+msgid "Finished upload"
+msgstr "Надсилання закінчене"
+
+msgid "Follow selected image"
+msgstr "Йти за виділеним знімком"
+
+msgid "From existing image layer"
+msgstr "З поточного шару зображень"
+
+msgid "From which source do you want to import images to the Mapillary layer?"
+msgstr "З яких джерел ви бажаєте імпортувати зображення до шару Mapillary?"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "Дати дорогу"
+
+msgid "Go forward"
+msgstr "Вперед"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr ""
+"Перейдіть в налаштування та увійдіть в Mapillary перед надсиланням даних."
+
+msgid "I got it, close this."
+msgstr "Зрозуміло, закрити вікно."
+
+msgid "Image actions"
+msgstr "Дії над знімком"
+
+msgid "Image detections"
+msgstr "Розпізнавання образів"
+
+msgid "Image info"
+msgstr "Відомості про зображення"
+
+msgid "Image key"
+msgstr "Ключ знімка"
+
+msgid "Images from my file system"
+msgstr "Зображення з моєї файлової системи"
+
+msgid "Import"
+msgstr "Імпортувати"
+
+msgid "Import exception"
+msgstr "Обмеження імпорту"
+
+msgid "Import local pictures"
+msgstr "Імпортувати локальні знімкки"
+
+msgid "Import pictures"
+msgstr "Імпортувати знімки"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "Імпортувати знімки до шару Mapillary"
+
+msgid "Imported images"
+msgstr "Імпортовані знімки"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "Імпортований {0} знімок"
+msgstr[1] "Імпортовано {0} знімки"
+msgstr[2] "Імпортовано {0} знімків"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "Перехрещення з другорядною дорогою"
+
+msgid ""
+"It can be activated by clicking the left button at the bottom of this "
+"message or the button in the toolbar on the left, which uses the same icon."
+msgstr ""
+"Її можна активувати клацнувши лівою кнопкою миші внизу цього повідомлення "
+"або кнопкою на панелі інструментів ліворуч, з таким самим значком."
+
+msgid "Join mode"
+msgstr "Режим з’єднування"
+
+msgid "Join/unjoin pictures"
+msgstr "З’єднати/роз’єднати зображення"
+
+msgid "Jump to blue"
+msgstr "Перейти до блакитної"
+
+msgid "Jump to red"
+msgstr "Перейти до червоної"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "Перейти до зображення з іншого боку від блакитної лінії"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "Перейти до знімку з іншого боку від червоної лінії"
+
+msgid "Key copied to clipboard"
+msgstr "Ключ скопійований до буфера обміну"
+
+msgid "Login"
+msgstr "Увійти"
+
+msgid "Login successful, return to JOSM."
+msgstr "Вдалий вхід, повертаємось в JOSM."
+
+msgid "Logout"
+msgstr "Вихід"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "Напрямок руху"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Знімки Mapillary"
+
+msgid "Mapillary changeset"
+msgstr "Набір змін Mapillary"
+
+msgid "Mapillary filter"
+msgstr "Фільтр Mapillary"
+
+msgid "Mapillary history"
+msgstr "Історія Mapillary"
+
+msgid "Mapillary layer"
+msgstr "Mapillary"
+
+msgid "Mapillary login"
+msgstr "Вхід в Mapillary"
+
+msgid "Mapillary object layer"
+msgstr "Шар обʼєктів Mapillary"
+
+msgid "Mapillary objects"
+msgstr "Обʼєкти Mapillary"
+
+msgid "Months"
+msgstr "Місяці"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr ""
+"Пересуватись до місця де був зроблений знімок кнопками Наступний/Попередній"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "Переміщено {0} зображення"
+msgstr[1] "Переміщено {0} зображення"
+msgstr[2] "Переміщено {0} зображень"
+
+msgid "Next picture"
+msgstr "Наступний знімок"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "В’їзд заборонено"
+
+msgid "No image selected"
+msgstr "Не обрано жодного зображення"
+
+msgid "No images found"
+msgstr "Знімків не знайдено"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "Обгін заборонений"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "Стоянка заборонена"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "Поворот заборонений"
+
+msgid "Not Logged in to Mapillary"
+msgstr "Не увішли до Mapillary"
+
+msgid "Not older than: "
+msgstr "Не старіше ніж: "
+
+#. i18n: Spinner label in JOSM settings
+msgid "Number of images to be pre-fetched (forwards and backwards)"
+msgstr "Кількість знімків для попереднього завантаження (вперед та назад)"
+
+msgid "Only images with signs"
+msgstr "Тільки знімки зі знаками"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "Відкрити діалог набору змін Mapillary"
+
+msgid "Open Mapillary filter dialog"
+msgstr "Відкрити діалог фільтра Mapillary"
+
+msgid "Open Mapillary history dialog"
+msgstr "Відкрити історію Mapillary"
+
+msgid "Open Mapillary layer"
+msgstr "Відкрити шар Mapillary"
+
+msgid "Open Mapillary window"
+msgstr "Відкрити вікно Mapillary"
+
+msgid "Pause"
+msgstr "Пауза"
+
+msgid "Pauses the walk."
+msgstr "Призупиняє перегляд"
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "Пішохідний перехід"
+
+msgid "Play"
+msgstr "Пуск"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "Натисніть \"{0}\" для завантаження зображень"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "Попередній перегляд зображень при наведенні курсору на їх значок"
+
+msgid "Previous picture"
+msgstr "Попередній знімок"
+
+msgid "Redo"
+msgstr "Повернути"
+
+msgid "Reset"
+msgstr "Скинути"
+
+msgid "Rewrite imported images"
+msgstr "Перезаписати імпортовані зображення"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "Круг"
+
+msgid "Select a directory"
+msgstr "Виберіть теку"
+
+msgid "Select directory to import images from"
+msgstr "Оберіть теку для імпорту зображень з неї"
+
+msgid "Select mode"
+msgstr "Режим виділення"
+
+msgid "Select the images you want to import"
+msgstr "Оберіть зображення для імпорту"
+
+msgid "Sequence key"
+msgstr "Ключ послідовності"
+
+msgid "Show detections on top of image"
+msgstr "Показувати виявлені образи поверх зображення"
+
+msgid "Shows the next picture in the sequence"
+msgstr "Показує наступний знімок послідовності"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "Показує попередній знімок послідовності"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "Обмеження швидкості"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "Стоп"
+
+msgid "Stops the walk."
+msgstr "Зупиняє перегляд."
+
+msgid "Submit changeset"
+msgstr "Надіслати набір змін"
+
+msgid "Submit the current changeset"
+msgstr "Надіслати поточний набір змін"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "Надіслати поточний набір змін до Mapillary"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "Надсилання набору змін Mapillary"
+
+msgid "Submitting changeset to server…"
+msgstr "Надсилання змін на сервер…"
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "Підтримувані формати зображень (JPG та PNG)"
+
+msgid "Tag conflict"
+msgstr "Конфлікт теґів"
+
+msgid ""
+"The Mapillary layer has stopped downloading images, because the requested "
+"area is too big!"
+msgstr ""
+"Завантаження знімків до шару Mapillary призупинено через надмірну розмір "
+"ділянки для завантаження!"
+
+msgid ""
+"The Mapillary plugin now uses a separate panel to display extra information "
+"(like the image key) and actions for the currently selected Mapillary image "
+"(like viewing it in a browser)."
+msgstr ""
+"Втулок Mapillary тепер використовує окрему панель для показу додаткової "
+"інформації (наприклад, ключа зображення) і дії для поточного зображення "
+"Mapillary (наприклад, перегляд в оглядачі)."
+
+msgid "There are currently no layers with geotagged images!"
+msgstr "Шар зображень з геопривʼязкою відсутній!"
+
+#, java-format
+msgid ""
+"To solve this problem, you could switch to download mode ''{0}'' and load "
+"Mapillary images for a smaller portion of the map."
+msgstr ""
+"Для розвʼязання цієї проблеми ви можете перемикнутися в режим завантаження "
+"''{0}'' та завантажити знімки Mapillary для меншої ділянки мапи."
+
+msgid ""
+"To solve this problem, you could zoom in and load a smaller area of the map."
+msgstr ""
+"Для розвʼязання цієї проблеми ви можете наблизитись або завантажити меншу "
+"ділянку мапи."
+
+msgid "Too many map objects, zoom in to see all."
+msgstr "Забагато обʼєктів, треба наблизитись, щоб побачити їх всі."
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "Всього знімків Mapillary: {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "Обернуто {0} зображення"
+msgstr[1] "Обернуто {0} зображення"
+msgstr[2] "Обернуто {0} зображень"
+
+msgid "Undo"
+msgstr "Скасувати"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "Нерівна дорога"
+
+msgid "Update"
+msgstr "Оновити"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "Надсилання: {0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "Використовувати 24-годинний формат"
+
+msgid "User"
+msgstr "Користувач"
+
+msgid "View in browser"
+msgstr "Подивитись в оглядачі"
+
+msgid "Wait for full quality pictures"
+msgstr "Чекати якісних фотографій"
+
+msgid "Walk mode"
+msgstr "Пішохідний режим"
+
+#. i18n: Checkbox label in JOSM settings
+msgid ""
+"When opening Mapillary image in web browser, show the blur editor instead of"
+" the image viewer"
+msgstr ""
+"Під час відкривання знімка Mapillary у веб-оглядачі, показувати редактор "
+"розмивання замість перегляду знімка"
+
+msgid "Which image layers do you want to import into the Mapillary layer?"
+msgstr "Які шари зображень ви бажаєте імпортувати до шару Mapillary?"
+
+msgid "Years"
+msgstr "Роки"
+
+msgid "You are currently not logged in."
+msgstr "Ви ще не ввійшли."
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "Ви увійшли як  ''{0}''."
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr "Ви не увійшли, будь ласка, здійсніть вхід в налаштуваннях  Mapillary"
+
+#, java-format
+msgid "You have successfully uploaded {0} images to mapillary.com"
+msgstr "Ви завантажили {0} знімок(ів) до mapillary.com"
+
+msgid "Zoom to selected image"
+msgstr "Масштабувати до виділеного знімка"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "Масштабувати до поточного виділеного знімка Mapillary"
+
+msgid "approved"
+msgstr "затверджено"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "області із завантаженими даними OSM"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "все, що є у видимій області"
+
+msgid "image has no key"
+msgstr "знімок не має ключа"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "тільки під час отримання запиту вручну"
+
+msgid "pending"
+msgstr "у черзі"
+
+msgid "rejected"
+msgstr "відхилено"
+
+msgid "sequence has no key"
+msgstr "послідовність не має ключа"
+
+msgid "unknown user"
+msgstr "невідомий користувач"
+
+#, java-format
+msgid ""
+"{0}\n"
+"Could not read map objects from URL\n"
+"{1}!"
+msgstr ""
+"{0}\n"
+"Не вийшло отримати обʼєкти мапи за посиланням URL\n"
+"{1}!"
+
+#. i18n: {0} is the layer name, {1} the number of images in it
+#, java-format
+msgid "{0} ({1} images)"
+msgstr "{0} ({1} знімків)"
+
+#, java-format
+msgid "{0} detections"
+msgstr "{0} образів"
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "{0} завантежених знімків"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "{0} знімків всього"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{0} знімків в {1} послідовностях"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr "{0} знімків надіслано, ключ набору змін: {1}, стан: {2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "{0} імпортованих знімків"
+
+#, java-format
+msgid "{0} sequences, each containing between {1} and {2} images (ø {3})"
+msgstr "{0} послідовностей, кожна містить від {1} до {2} знімків (ø {3})"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr "Дозволяє користувачам використовувати знімки з mapillary.com"
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/zh_CN.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/zh_CN.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/zh_CN.po	(revision 34317)
@@ -0,0 +1,461 @@
+# Translations for the JOSM plugin 'Mapillary' (zh_CN)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: jie x <qa003qa003@hotmail.com>, 2018\n"
+"Language-Team: Chinese (China) (https://www.transifex.com/josm/teams/2544/zh_CN/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: zh_CN\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgid "2 images joined"
+msgstr "加入了2张图片"
+
+msgid "2 images unjoined"
+msgstr "2张图片未加入"
+
+#, java-format
+msgid ""
+"A tag with key <i>{0}</i> is already present on the selected OSM object."
+msgstr "包含键 <i>{0}</i> 的标签已在所选OSM对象上出现。"
+
+msgid "Add Mapillary tag"
+msgstr "添加Mapillary标签"
+
+msgid "All images in a directory"
+msgstr "在某一目录下的所有图像"
+
+msgid ""
+"An exception occured while trying to submit a changeset. If this happens "
+"repeatedly, consider reporting a bug via the Help menu. If this message "
+"appears for the first time, simply try it again. This might have been an "
+"issue with the internet connection."
+msgstr "在试图提交修改集合时发生意外。若反复出现，考虑通过帮助菜单报告漏洞。若第一次出现，重试一次，可能是互联网连接问题。"
+
+msgid "Cancel"
+msgstr "取消"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr "修改集合上传失败由于{0}错误 ''{1} {2}''!"
+
+msgid "Choose signs"
+msgstr "选择标志"
+
+msgid "Continues with the paused walk."
+msgstr "继续已暂停的步行"
+
+msgid "Could not import a geotagged image to the Mapillary layer!"
+msgstr "无法将地理标签图像导入Mapillary层！"
+
+#, java-format
+msgid "Could not import the directory ''{0}''!"
+msgstr "无法导入目录''{0}''！"
+
+#, java-format
+msgid "Could not import the image ''{0}''!"
+msgstr "无法导入图像''{0}''！"
+
+msgid "Current Mapillary changeset"
+msgstr "当前Mapillary修改集合"
+
+msgid "Days"
+msgstr "日"
+
+msgid "Delete after upload"
+msgstr "上传后删除"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "已删除 {0} 张图像"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "显示图片拍摄时间"
+
+msgid "Displays detail information on the currently selected Mapillary image"
+msgstr "在当前选择的Mapillary图像上显示详细信息"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr "显示Mapillary侦测到的地图对象"
+
+#, java-format
+msgid ""
+"Do you really want to replace the current value <i>{0}</i> with the new "
+"value <i>{1}</i>?"
+msgstr "您真的想要将当前值 <i>{0}</i> 替换为新值 <i>{1}</i>吗？"
+
+msgid "Download Mapillary images in current view"
+msgstr "在现有视图下载Mapillary图像"
+
+msgid "Download mode"
+msgstr "下载模式"
+
+msgid "Downloaded images"
+msgstr "已下载图像"
+
+msgid "Downloading"
+msgstr "正在下载"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr "启用实验性功能（可能不稳定）"
+
+msgid "Explore"
+msgstr "浏览"
+
+msgid "Export all images"
+msgstr "导出所有图像"
+
+msgid "Export selected images"
+msgstr "导出选定图像"
+
+msgid "Export selected sequence"
+msgstr "导出所选序列"
+
+msgid "Follow selected image"
+msgstr "跟随所选图像"
+
+msgid "From existing image layer"
+msgstr "从现有的图层中"
+
+msgid "From which source do you want to import images to the Mapillary layer?"
+msgstr "您想从何来源导入图像至Mapillary层？"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "让道"
+
+msgid "Go forward"
+msgstr "向前"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr "前往设置并在上传前登陆Mapillary"
+
+msgid "I got it, close this."
+msgstr "我已知晓，关闭该窗口"
+
+msgid "Image info"
+msgstr "图片信息"
+
+msgid "Images from my file system"
+msgstr "我文件系统中的图像"
+
+msgid "Import"
+msgstr "输入"
+
+msgid "Import exception"
+msgstr "导入发生意外"
+
+msgid "Import local pictures"
+msgstr "导入本地图片"
+
+msgid "Import pictures"
+msgstr "导入图片"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "将图像导入Mapillary层"
+
+msgid "Imported images"
+msgstr "已导入图像"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "已导入 {0} 张图像"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "危险交叉"
+
+msgid ""
+"It can be activated by clicking the left button at the bottom of this "
+"message or the button in the toolbar on the left, which uses the same icon."
+msgstr "单击此信息左下方的按钮或工具条左侧的相同按钮以启用它"
+
+msgid "Join mode"
+msgstr "合并模式"
+
+msgid "Join/unjoin pictures"
+msgstr "合并/分离图像"
+
+msgid "Key copied to clipboard"
+msgstr "已复制键至剪贴板"
+
+msgid "Login"
+msgstr "登录"
+
+msgid "Login successful, return to JOSM."
+msgstr "登录成功，返回 JOSM。"
+
+msgid "Logout"
+msgstr "注销"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "强制性指示（任何）"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Mapillary Images"
+
+msgid "Mapillary changeset"
+msgstr "Mapillary修改集合"
+
+msgid "Mapillary filter"
+msgstr "Mapillary过滤器"
+
+msgid "Mapillary history"
+msgstr "Mapillary历史"
+
+msgid "Mapillary layer"
+msgstr "Mapillary图层"
+
+msgid "Mapillary object layer"
+msgstr "Mapillary对象层"
+
+msgid "Months"
+msgstr "月"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr "使用前进后退按钮移动至图片位置"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "已移动 {0} 张图像"
+
+msgid "Next picture"
+msgstr "前一图片"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "禁止入内"
+
+msgid "No image selected"
+msgstr "未选择图像"
+
+msgid "No images found"
+msgstr "没有找到图像"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "禁止超车"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "禁止停车"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "禁止掉头"
+
+msgid "Not older than: "
+msgstr "不大于 "
+
+msgid "Only images with signs"
+msgstr "只有有标志的图像"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "打开Mapillary修改集合对话框"
+
+msgid "Open Mapillary filter dialog"
+msgstr "打开Mapillary过滤器对话框"
+
+msgid "Open Mapillary history dialog"
+msgstr "打开Mapillary历史对话框"
+
+msgid "Open Mapillary window"
+msgstr "打开Mapillary窗口"
+
+msgid "Pause"
+msgstr "暂停"
+
+msgid "Pauses the walk."
+msgstr "暂停步行"
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "人行道十字路口"
+
+msgid "Play"
+msgstr "播放"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "按\"{0}\"来下载图像"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "悬停在图标上时预览图像"
+
+msgid "Previous picture"
+msgstr "后一图片"
+
+msgid "Redo"
+msgstr "重做"
+
+msgid "Reset"
+msgstr "重新设定"
+
+msgid "Rewrite imported images"
+msgstr "重写已导入图像"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "环岛"
+
+msgid "Select a directory"
+msgstr "选择文件夹"
+
+msgid "Select directory to import images from"
+msgstr "选择导入图像来源目录"
+
+msgid "Select the images you want to import"
+msgstr "选择您想要导入的图像"
+
+msgid "Shows the next picture in the sequence"
+msgstr "按序显示下一个图像"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "按序显示上一个图像"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "限速"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "停车让行"
+
+msgid "Stops the walk."
+msgstr "停止步行"
+
+msgid "Submit changeset"
+msgstr "提交修改集合"
+
+msgid "Submit the current changeset"
+msgstr "提交现有的修改集合"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "提交现有的修改集合至Mapillary"
+
+msgid "Submitting changeset to server…"
+msgstr "正在提交修改集合至服务器..."
+
+msgid "Tag conflict"
+msgstr "标签冲突"
+
+msgid ""
+"The Mapillary plugin now uses a separate panel to display extra information "
+"(like the image key) and actions for the currently selected Mapillary image "
+"(like viewing it in a browser)."
+msgstr "Mapillary插件现在使用独立的面板来显示额外信息（比如图片键值）和已选的Mapillary图像的操作（就像在浏览器中那样）"
+
+msgid "There are currently no layers with geotagged images!"
+msgstr "当前没有图层含有地理标签图像"
+
+msgid "Undo"
+msgstr "撤消"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "不平整的路"
+
+msgid "Update"
+msgstr "更新"
+
+msgid "Upload selected sequence"
+msgstr "上传所选序列"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "使用24小时格式"
+
+msgid "User"
+msgstr "用户"
+
+msgid "Wait for full quality pictures"
+msgstr "等待完整品质图像"
+
+msgid "Walk mode"
+msgstr "步行模式"
+
+msgid "Which image layers do you want to import into the Mapillary layer?"
+msgstr "您想将哪个图层导入Mapillary层？"
+
+msgid "Years"
+msgstr "年"
+
+msgid "You are currently not logged in."
+msgstr "您尚未登录。"
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "您已登录为“{0}”。"
+
+msgid "Zoom to selected image"
+msgstr "缩放至选定图片"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "缩放至所选Mapillary图像"
+
+msgid "approved"
+msgstr "已通过"
+
+msgid "pending"
+msgstr "挂起中"
+
+msgid "rejected"
+msgstr "已退回"
+
+#. i18n: {0} is the layer name, {1} the number of images in it
+#, java-format
+msgid "{0} ({1} images)"
+msgstr "{0} ({1}份图像)"
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "{0}下载的图像"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "总共{0}份图像"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{0}图像在{1}序列中"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr "{0}图像已提交，修改集合编号：{1}，状态：{2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "{0}导入的图像"
+
+#, java-format
+msgid "{0} sequences, each containing between {1} and {2} images (ø {3})"
+msgstr "{0}序列，都包含在{1}和{2}间的图像 (ø {3})"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr "可使用户用 mapillary.com 上的图片工作"
Index: applications/editors/josm/plugins/MicrosoftStreetside/poSrc/zh_TW.po
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/poSrc/zh_TW.po	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/poSrc/zh_TW.po	(revision 34317)
@@ -0,0 +1,634 @@
+# Translations for the JOSM plugin 'Mapillary' (zh_TW)
+# Copyright (C) 2018 
+# This file is distributed under the same license as the josm-plugin_Mapillary package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+# 
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: josm-plugin_Mapillary v1.5.10\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2018-01-21 21:47+0000\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: floscher, 2018\n"
+"Language-Team: Chinese (Taiwan) (https://www.transifex.com/josm/teams/2544/zh_TW/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: zh_TW\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgid "2 images joined"
+msgstr "加入了 2 個影像"
+
+msgid "2 images unjoined"
+msgstr "退出了 2 個影像"
+
+#, java-format
+msgid ""
+"A tag with key <i>{0}</i> is already present on the selected OSM object."
+msgstr "有鍵 <i>{0}</i>已經存在選取的 OSM 物件上面了。"
+
+msgid "Add Mapillary tag"
+msgstr "新增 Mapillary 標籤"
+
+msgid "All images in a directory"
+msgstr "所有圖片都在目錄裡"
+
+msgid "All map objects loaded."
+msgstr "所以地圖物件都載入了。"
+
+msgid ""
+"An exception occured while trying to submit a changeset. If this happens "
+"repeatedly, consider reporting a bug via the Help menu. If this message "
+"appears for the first time, simply try it again. This might have been an "
+"issue with the internet connection."
+msgstr "嘗試送出變更組合時發生例外狀況發生了。如果重覆發生的話，請考慮透過說明選單回報臭蟲。如果訊息第一次出次，請再試一次，也許是網路連線出問題。"
+
+msgid "Cancel"
+msgstr "取消"
+
+#, java-format
+msgid "Changeset upload failed with {0} error ''{1} {2}''!"
+msgstr "上傳變更組合因 {0} error ''{1} {2}'' 失敗！"
+
+msgid "Choose signs"
+msgstr "選取標誌"
+
+msgid "Continues with the paused walk."
+msgstr "繼續暫停的走動。"
+
+msgid "Copy key"
+msgstr "複製鍵值"
+
+msgid "Could not import a geotagged image to the Mapillary layer!"
+msgstr "無法匯入有地理標記圖片到 Mapillary 圖層！"
+
+#, java-format
+msgid "Could not import the directory ''{0}''!"
+msgstr "無法匯入目錄 ''{0}''！"
+
+#, java-format
+msgid "Could not import the image ''{0}''!"
+msgstr "無法匯入圖片 ''{0}''！"
+
+#, java-format
+msgid "Could not open the URL {0} in a browser"
+msgstr "無法用瀏覽器打開網址 {0}"
+
+#, java-format
+msgid "Could not read from URL {0}!"
+msgstr "無法讀取網址 {0}！"
+
+msgid "Current Mapillary changeset"
+msgstr "目前的 Mapillary 變更組合"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Cut off sequences at download bounds"
+msgstr "在下載邊界切斷片段"
+
+msgid "Days"
+msgstr "日"
+
+msgid "Delete after upload"
+msgstr "上傳後刪除"
+
+#, java-format
+msgid "Deleted {0} image"
+msgid_plural "Deleted {0} images"
+msgstr[0] "刪除了 {0} 個影像"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Display hour when the picture was taken"
+msgstr "顯示圖片拍攝時的小時時間"
+
+msgid "Displays detail information on the currently selected Mapillary image"
+msgstr "顯示目前選取的 Mapillary 圖片的詳細資訊"
+
+msgid "Displays objects detected by Mapillary from their street view imagery"
+msgstr "顯示 Mapillary 從街景偵測到的物件"
+
+msgid "Displays the layer displaying the map objects detected by Mapillary"
+msgstr "顯示 Mapillary 偵測出來的地圖物件的圖層"
+
+#, java-format
+msgid ""
+"Do you really want to replace the current value <i>{0}</i> with the new "
+"value <i>{1}</i>?"
+msgstr "你真的要將目前的值 <i>{0}</i> 覆寫為新的值 <i>{1}</i> 嗎？"
+
+msgid "Download Mapillary images in current view"
+msgstr "依據目前檢視下載 Mapillary 影像"
+
+msgid "Download mode"
+msgstr "下載模式"
+
+msgid "Downloaded images"
+msgstr "下載的影像"
+
+msgid "Downloading"
+msgstr "正在下載"
+
+msgid "Downloading Mapillary images"
+msgstr "下載 Mapillary 影像"
+
+msgid "Downloading map objects failed!"
+msgstr "下載地圖物件物敗！"
+
+msgid "Downloading map objects…"
+msgstr "下載地圖物件..."
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Enable experimental beta-features (might be unstable)"
+msgstr "啟用實驗性質的 beta 功能 (可能不穩定)"
+
+msgid "Explore"
+msgstr "瀏覽"
+
+msgid "Export Mapillary images"
+msgstr "匯出Mapillary圖片"
+
+msgid "Export all images"
+msgstr "匯出所有圖片"
+
+msgid "Export selected images"
+msgstr "匯出選取圖片"
+
+msgid "Export selected sequence"
+msgstr "匯出選取片段"
+
+msgid "Exporting Mapillary Images"
+msgstr "匯出 Mapillary 圖片"
+
+msgid "Finished upload"
+msgstr "上傳完畢"
+
+msgid "Follow selected image"
+msgstr "跟隨選取圖片"
+
+msgid "From existing image layer"
+msgstr "跟隨既有圖片圖層"
+
+msgid "From which source do you want to import images to the Mapillary layer?"
+msgstr "你要從那個來源匯入圖片到 Mapillary 圖層？"
+
+#. i18n: traffic sign
+msgid "Give way"
+msgstr "禮讓路口"
+
+msgid "Go forward"
+msgstr "往前。"
+
+msgid "Go to setting and log in to Mapillary before uploading."
+msgstr "移至設定和上傳前登錄 Mapillary。"
+
+msgid "I got it, close this."
+msgstr "我知道了，關掉吧。"
+
+msgid "Image actions"
+msgstr "圖片動作"
+
+msgid "Image detections"
+msgstr "圖片偵測"
+
+msgid "Image info"
+msgstr "影像資訊"
+
+msgid "Image key"
+msgstr "圖片鍵值"
+
+msgid "Images from my file system"
+msgstr "從我檔案系統的圖片"
+
+msgid "Import"
+msgstr "匯入"
+
+msgid "Import exception"
+msgstr "匯入排除"
+
+msgid "Import local pictures"
+msgstr "匯入本機圖片"
+
+msgid "Import pictures"
+msgstr "匯入圖片"
+
+msgid "Import pictures into Mapillary layer"
+msgstr "匯入圖片到 Mapillary 圖層"
+
+msgid "Imported images"
+msgstr "匯入的圖片"
+
+#, java-format
+msgid "Imported {0} image"
+msgid_plural "Imported {0} images"
+msgstr[0] "匯入了 {0} 個影像"
+
+#. i18n: traffic sign
+msgid "Intersection danger"
+msgstr "路口危險"
+
+msgid ""
+"It can be activated by clicking the left button at the bottom of this "
+"message or the button in the toolbar on the left, which uses the same icon."
+msgstr "可以藉由在這則訊息的底部按左鍵啟動，或是工具列左邊相同的圖示。"
+
+msgid "Join mode"
+msgstr "加入模式"
+
+msgid "Join/unjoin pictures"
+msgstr "加入/退出圖片"
+
+msgid "Jump to blue"
+msgstr "跳到藍色"
+
+msgid "Jump to red"
+msgstr "跳到紅色"
+
+msgid "Jumps to the picture at the other side of the blue line"
+msgstr "跳到藍線另一邊的圖片"
+
+msgid "Jumps to the picture at the other side of the red line"
+msgstr "跳到紅線另一邊的圖片"
+
+msgid "Key copied to clipboard"
+msgstr "鍵複製到剪貼簿"
+
+msgid "Login"
+msgstr "登入"
+
+msgid "Login successful, return to JOSM."
+msgstr "登入成功，回去 JOSM。"
+
+msgid "Logout"
+msgstr "登出"
+
+#. i18n: traffic sign
+msgid "Mandatory direction (any)"
+msgstr "強制性方向 (任何方向)"
+
+msgid "Mapillary"
+msgstr "Mapillary"
+
+msgid "Streetside"
+msgstr "Streetside"
+
+msgid "Mapillary Images"
+msgstr "Mapillary影像"
+
+msgid "Mapillary changeset"
+msgstr "Mapillary 變更組合"
+
+msgid "Mapillary filter"
+msgstr "Mapillary 篩選器"
+
+msgid "Mapillary history"
+msgstr "Mapillary 歷史記錄"
+
+msgid "Mapillary image"
+msgstr "Mapillary 圖片"
+
+msgid "Mapillary layer"
+msgstr "Mapillary圖層"
+
+msgid "Mapillary login"
+msgstr "Mapillary 登入"
+
+msgid "Mapillary object layer"
+msgstr "Mapillary 物件圖層"
+
+msgid "Mapillary objects"
+msgstr "Mapillary 物件"
+
+msgid "Months"
+msgstr "月"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Move to picture''s location with next/previous buttons"
+msgstr "用下一張/前一張按鈕移動到圖片位置"
+
+#, java-format
+msgid "Moved {0} image"
+msgid_plural "Moved {0} images"
+msgstr[0] "移動了 {0} 個影像"
+
+msgid "Next picture"
+msgstr "下一張圖片"
+
+#. i18n: traffic sign
+msgid "No entry"
+msgstr "沒有輸入"
+
+msgid "No image selected"
+msgstr "沒有選取圖片"
+
+msgid "No images found"
+msgstr "找不到影像"
+
+#. i18n: traffic sign
+msgid "No overtaking"
+msgstr "禁止超車"
+
+#. i18n: traffic sign
+msgid "No parking"
+msgstr "禁止停車"
+
+#. i18n: traffic sign
+msgid "No turn"
+msgstr "禁止轉彎"
+
+msgid "Not Logged in to Mapillary"
+msgstr "沒有登入 Mapillary"
+
+msgid "Not older than: "
+msgstr "不早於： "
+
+#. i18n: Spinner label in JOSM settings
+msgid "Number of images to be pre-fetched (forwards and backwards)"
+msgstr "要預載的圖片數目 (向前和向後)"
+
+msgid "Only images with signs"
+msgstr "只有裡面有標誌的圖片"
+
+msgid "Open Mapillary changeset dialog"
+msgstr "開啟 Mapillary 變更組合對話框"
+
+msgid "Open Mapillary filter dialog"
+msgstr "開啟 Mapillary 篩選器對話框"
+
+msgid "Open Mapillary history dialog"
+msgstr "開啟 Mapillary 歷史對話框"
+
+msgid "Open Mapillary layer"
+msgstr "開啟Mapillary圖層 "
+
+msgid "Open Mapillary window"
+msgstr "開啟 Mapillary 視窗"
+
+msgid "Pause"
+msgstr "暫停"
+
+msgid "Pauses the walk."
+msgstr "暫停走動"
+
+#. i18n: traffic sign
+msgid "Pedestrian crossing"
+msgstr "行人穿越"
+
+msgid "Play"
+msgstr "播放"
+
+#, java-format
+msgid "Press \"{0}\" to download images"
+msgstr "按 \"{0}\" 下載影像"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Preview images when hovering its icon"
+msgstr "滑動圖示過去時預纜圖片"
+
+msgid "Previous picture"
+msgstr "上一張圖片"
+
+msgid "Redo"
+msgstr "重做"
+
+msgid "Reset"
+msgstr "重新設定"
+
+msgid "Rewrite imported images"
+msgstr "重新寫入匯入圖片"
+
+#. i18n: traffic sign
+msgid "Roundabout"
+msgstr "圓環"
+
+msgid "Select a directory"
+msgstr "選取目錄"
+
+msgid "Select directory to import images from"
+msgstr "選取要匯入圖片的選取目錄"
+
+msgid "Select mode"
+msgstr "選取模式"
+
+msgid "Select the images you want to import"
+msgstr "選取你想要匯入的圖片"
+
+msgid "Sequence key"
+msgstr "片段鍵值"
+
+msgid "Show detections on top of image"
+msgstr "在圖片上顯示方向"
+
+msgid "Shows the next picture in the sequence"
+msgstr "從片段顯示下一張"
+
+msgid "Shows the previous picture in the sequence"
+msgstr "從片段顯示上一張圖片"
+
+#. i18n: traffic sign
+msgid "Speed limit"
+msgstr "速限"
+
+#. i18n: traffic sign
+msgid "Stop"
+msgstr "禁止通行"
+
+msgid "Stops the walk."
+msgstr "停止走動"
+
+msgid "Submit changeset"
+msgstr "提出變更組合"
+
+msgid "Submit the current changeset"
+msgstr "提出目前的變更組合"
+
+#. CHECKSTYLE.OFF: LineLength
+msgid "Submit the current changeset to Mapillary"
+msgstr "提出目前的變更組合到 Mapillary"
+
+msgid "Submitting Mapillary Changeset"
+msgstr "送出 Mapillary 變更組合"
+
+msgid "Submitting changeset to server…"
+msgstr "送出變更組合到伺服器..."
+
+msgid "Supported image formats (JPG and PNG)"
+msgstr "支援圖片格式 (JPG 和 PNG)"
+
+msgid "Tag conflict"
+msgstr "標籤衝突"
+
+msgid ""
+"The Mapillary layer has stopped downloading images, because the requested "
+"area is too big!"
+msgstr "Mapillary 圖層已經停止下載圖片，因為要求的區域太大了！"
+
+msgid ""
+"The Mapillary plugin now uses a separate panel to display extra information "
+"(like the image key) and actions for the currently selected Mapillary image "
+"(like viewing it in a browser)."
+msgstr ""
+"如今 Mapillary 外掛使用獨立的面版顯示額外的訊息 (像是圖片鍵)，以及目前選取 Mapillary 圖片可採取的行動 (例如在瀏覽器檢視)。"
+
+msgid "There are currently no layers with geotagged images!"
+msgstr "目前圖層中並無地理標記的圖片！"
+
+#, java-format
+msgid ""
+"To solve this problem, you could switch to download mode ''{0}'' and load "
+"Mapillary images for a smaller portion of the map."
+msgstr "要解決這項問題，請切換到下載模式 ''{0}''，並且選取地圖比較小的部分來載入Mapillary 圖片。"
+
+msgid ""
+"To solve this problem, you could zoom in and load a smaller area of the map."
+msgstr "要解決這項問題，你可以放大然後載入地圖比較小的部分。"
+
+msgid "Too many map objects, zoom in to see all."
+msgstr "太多地圖物件，放大後來看所有物件。"
+
+#, java-format
+msgid "Total Mapillary images: {0}"
+msgstr "所有 Mapillary 圖片： {0}"
+
+#, java-format
+msgid "Turned {0} image"
+msgid_plural "Turned {0} images"
+msgstr[0] "旋轉了 {0} 個影像"
+
+msgid "Undo"
+msgstr "復原"
+
+#. i18n: traffic sign
+msgid "Uneven road"
+msgstr "坎坷的道路"
+
+msgid "Update"
+msgstr "更新"
+
+#, java-format
+msgid "Uploading: {0}"
+msgstr "上傳中：{0}"
+
+#. i18n: Checkbox label in JOSM settings
+msgid "Use 24 hour format"
+msgstr "使用 24 小時格式"
+
+msgid "User"
+msgstr "使用者"
+
+msgid "View in browser"
+msgstr "在瀏覽器中觀看"
+
+msgid "Wait for full quality pictures"
+msgstr "等待全品質的圖片"
+
+msgid "Walk mode"
+msgstr "行走模式"
+
+#. i18n: Checkbox label in JOSM settings
+msgid ""
+"When opening Mapillary image in web browser, show the blur editor instead of"
+" the image viewer"
+msgstr "當你在網頁瀏覽器開啟 Mapillary 圖片時，顯示模糊化編輯器而不是圖片檢視器"
+
+msgid "Which image layers do you want to import into the Mapillary layer?"
+msgstr "你要匯入那個圖片圖層到 Mapillary 圖層？"
+
+msgid "Years"
+msgstr "年"
+
+msgid "You are currently not logged in."
+msgstr "你目前沒登入。"
+
+#, java-format
+msgid "You are logged in as ''{0}''."
+msgstr "你已經登入為 ''{0}''。"
+
+msgid "You are not logged in, please log in to Mapillary in the preferences"
+msgstr "你並沒有登入，請在偏好設定登入 Mapillary"
+
+#, java-format
+msgid "You have successfully uploaded {0} images to mapillary.com"
+msgstr "你成功上傳 {0} 圖片到 mapillary.com"
+
+msgid "Zoom to selected image"
+msgstr "縮放到選取的圖片"
+
+msgid "Zoom to the currently selected Mapillary image"
+msgstr "縮放到目前選取的 Mapiilary 影像"
+
+msgid "approved"
+msgstr "批准"
+
+#. i18n: download mode for Mapillary images
+msgid "areas with downloaded OSM-data"
+msgstr "區域已經有下載下來的 OSM 資料"
+
+#. i18n: download mode for Mapillary images
+msgid "everything in the visible area"
+msgstr "所有東西都在可視範圍"
+
+msgid "image has no key"
+msgstr "圖片沒有鍵"
+
+#. i18n: download mode for Mapillary images
+msgid "only when manually requested"
+msgstr "只有當手動要求時"
+
+msgid "pending"
+msgstr "待決"
+
+msgid "rejected"
+msgstr "駁回"
+
+msgid "sequence has no key"
+msgstr "片段沒有鍵"
+
+msgid "unknown user"
+msgstr "未知的使用者"
+
+#, java-format
+msgid ""
+"{0}\n"
+"Could not read map objects from URL\n"
+"{1}!"
+msgstr ""
+"{0}\n"
+"無法從網址 {1} 讀取地圖物件！"
+
+#. i18n: {0} is the layer name, {1} the number of images in it
+#, java-format
+msgid "{0} ({1} images)"
+msgstr "{0} ({1} 圖片)"
+
+#, java-format
+msgid "{0} detections"
+msgstr "方向 {0} "
+
+#, java-format
+msgid "{0} downloaded images"
+msgstr "下載 {0} 張圖片"
+
+#, java-format
+msgid "{0} images in total"
+msgstr "總共 {0} 張圖片"
+
+#, java-format
+msgid "{0} images in {1} sequences"
+msgstr "{1} 片段有 {0} 張圖片"
+
+#, java-format
+msgid "{0} images submitted, Changeset key: {1}, State: {2}"
+msgstr "{0} 圖片提交，變更組合鍵：{1}，狀態： {2}"
+
+#, java-format
+msgid "{0} imported images"
+msgstr "匯入 {0} 張圖片"
+
+#, java-format
+msgid "{0} sequences, each containing between {1} and {2} images (ø {3})"
+msgstr "{0} 片段，每個片段含有 {1} 到 {2} 張圖片 (ø {3})"
+
+#. Plugin description for Mapillary
+msgid "Allows the user to work with pictures hosted at mapillary.com"
+msgstr "Mapillary外掛"
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImage.java	(revision 34317)
@@ -0,0 +1,339 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+
+/**
+ * Abstract superclass for all image objects. At the moment there are just 2,
+ * {@link StreetsideImportedImage} and {@link StreetsideImage}.
+ *
+ * @author nokutu
+ *
+ */
+public abstract class StreetsideAbstractImage implements Comparable<StreetsideAbstractImage> {
+	/**
+	 * If two values for field cd differ by less than EPSILON both values are
+	 * considered equal.
+	 */
+	private static final float EPSILON = 1e-5f;
+
+	protected String id;
+
+	/** The time the image was captured, in Epoch format. */
+	protected long cd;
+	/** Sequence of pictures containing this object. */
+	private StreetsideSequence sequence;
+
+	/** Position of the picture. */
+	protected LatLon latLon;
+	/** Direction of the picture. */
+	protected double he;
+	/** Temporal position of the picture until it is uploaded. */
+	private LatLon tempLatLon;
+	/**
+	 * When the object is being dragged in the map, the temporal position is stored
+	 * here.
+	 */
+	private LatLon movingLatLon;
+	/** Temporal direction of the picture until it is uploaded */
+	private double tempHe;
+	/**
+	 * When the object direction is being moved in the map, the temporal direction
+	 * is stored here
+	 */
+	protected double movingHe;
+	/** Whether the image must be drown in the map or not */
+	private boolean visible;
+
+	/**
+	 * Creates a new object in the given position and with the given direction.
+	 * {@link LatLon}
+	 *
+	 * @param id - the Streetside image id
+	 *
+	 * @param latLon
+	 *            The latitude and longitude of the image.
+	 * @param he
+	 *            The direction of the picture (0 means north im Mapillary
+	 *            camera direction is not yet supported in the Streetside plugin).
+	 */
+	protected StreetsideAbstractImage(final String id, final LatLon latLon, final double he) {
+		this.id = id;
+		this.latLon = latLon;
+		tempLatLon = this.latLon;
+		movingLatLon = this.latLon;
+		this.he = he;
+		tempHe = he;
+		movingHe = he;
+		visible = true;
+	}
+
+	/**
+	 * Creates a new object with the given id.
+	 *
+	 * @param id - the image id (All images require ids in Streetside)
+	 */
+	protected StreetsideAbstractImage(final String id) {
+		this.id = id;
+
+		visible = true;
+	}
+
+	/**
+	 * @return the id
+	 */
+	public String getId() {
+		return id;
+	}
+
+	/**
+	 * @param id
+	 *            the id to set
+	 */
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	/**
+	 * Returns the original direction towards the image has been taken.
+	 *
+	 * @return The direction of the image (0 means north and goes clockwise).
+	 */
+	public double getHe() {
+		return he;
+	}
+
+	/**
+	 * Returns the Epoch time when the image was captured.
+	 *
+	 * @return The long containing the Epoch time when the image was captured.
+	 */
+	public long getCd() {
+		return cd;
+	}
+
+	/**
+	 * Returns the date the picture was taken in DMY format.
+	 *
+	 * @return A String object containing the date when the picture was taken.
+	 */
+	public String getDate() {
+		final StringBuilder format = new StringBuilder(26);
+		format.append("m/d/YYYY");
+		if (StreetsideProperties.DISPLAY_HOUR.get()) {
+			if (StreetsideProperties.TIME_FORMAT_24.get()) {
+				format.append(" - HH:mm:ss");
+			} else {
+				format.append(" - h:mm:ss a");
+			}
+		}
+		return getDate(format.toString());
+	}
+
+	/**
+	 * Returns the date the picture was taken in the given format.
+	 *
+	 * @param format
+	 *            Format of the date. See {@link SimpleDateFormat}.
+	 * @return A String containing the date the picture was taken using the given
+	 *         format.
+	 * @throws NullPointerException
+	 *             if parameter format is <code>null</code>
+	 */
+	public String getDate(String format) {
+		final Date date = new Date(getCd());
+		final SimpleDateFormat formatter = new SimpleDateFormat(format, Locale.US);
+		formatter.setTimeZone(Calendar.getInstance().getTimeZone());
+		return formatter.format(date);
+	}
+
+	/**
+	 * Returns a LatLon object containing the original coordinates of the object.
+	 *
+	 * @return The LatLon object with the position of the object.
+	 */
+	public LatLon getLatLon() {
+		return latLon;
+	}
+
+	/**
+	 * Returns the direction towards the image has been taken.
+	 *
+	 * @return The direction of the image (0 means north and goes clockwise).
+	 */
+	public double getMovingHe() {
+		return movingHe;
+	}
+
+	/**
+	 * Returns a LatLon object containing the current coordinates of the object.
+	 * When you are dragging the image this changes.
+	 *
+	 * @return The LatLon object with the position of the object.
+	 */
+	public LatLon getMovingLatLon() {
+		return movingLatLon;
+	}
+
+	/**
+	 * Returns the sequence which contains this image. Never null.
+	 *
+	 * @return The StreetsideSequence object that contains this StreetsideImage.
+	 */
+
+	public StreetsideSequence getSequence() {
+		synchronized (this) {
+			if (sequence == null) {
+				sequence = new StreetsideSequence();
+				sequence.add(this);
+			}
+			return sequence;
+		}
+	}
+
+	/**
+	 * Returns the last fixed direction of the object.
+	 *
+	 * @return The last fixed direction of the object. 0 means north.
+	 */
+	public double getTempHe() {
+		return tempHe;
+	}
+
+	/**
+	 * Returns the last fixed coordinates of the object.
+	 *
+	 * @return A LatLon object containing.
+	 */
+	public LatLon getTempLatLon() {
+		return tempLatLon;
+	}
+
+	/**
+	 * Returns whether the object has been modified or not.
+	 *
+	 * @return true if the object has been modified; false otherwise.
+	 */
+	public boolean isModified() {
+		return !getMovingLatLon().equals(latLon) || Math.abs(getMovingHe() - cd) > EPSILON;
+	}
+
+	/**
+	 * Returns whether the image is visible on the map or not.
+	 *
+	 * @return True if the image is visible; false otherwise.
+	 */
+	public boolean isVisible() {
+		return visible;
+	}
+
+	/**
+	 * Moves the image temporally to another position
+	 *
+	 * @param x
+	 *            The movement of the image in longitude units.
+	 * @param y
+	 *            The movement of the image in latitude units.
+	 */
+	public void move(final double x, final double y) {
+		movingLatLon = new LatLon(tempLatLon.getY() + y, tempLatLon.getX() + x);
+	}
+
+	/**
+	 * If the StreetsideImage belongs to a StreetsideSequence, returns the next
+	 * image in the sequence.
+	 *
+	 * @return The following StreetsideImage, or null if there is none.
+	 */
+	public StreetsideAbstractImage next() {
+		synchronized (this) {
+			return getSequence().next(this);
+		}
+	}
+
+	/**
+	 * If the StreetsideImage belongs to a StreetsideSequence, returns the previous
+	 * image in the sequence.
+	 *
+	 * @return The previous StreetsideImage, or null if there is none.
+	 */
+	public StreetsideAbstractImage previous() {
+		synchronized (this) {
+			return getSequence().previous(this);
+		}
+	}
+
+	public void setHe(final double he) {
+		this.he = he;
+	}
+
+	/**
+	 * Sets the Epoch time when the picture was captured.
+	 *
+	 * @param cd
+	 *            Epoch time when the image was captured.
+	 */
+	public synchronized void setCd(final long cd) {
+		this.cd = cd;
+	}
+
+	public void setLatLon(final LatLon latLon) {
+		if (latLon != null) {
+			this.latLon = latLon;
+		}
+	}
+
+	/**
+	 * Sets the StreetsideSequence object which contains the StreetsideImage.
+	 *
+	 * @param sequence
+	 *            The StreetsideSequence that contains the StreetsideImage.
+	 * @throws IllegalArgumentException
+	 *             if the image is not already part of the
+	 *             {@link StreetsideSequence}. Call
+	 *             {@link StreetsideSequence#add(StreetsideAbstractImage)} first.
+	 */
+	public void setSequence(final StreetsideSequence sequence) {
+		synchronized (this) {
+			if (sequence != null && !sequence.getImages().contains(this)) {
+				throw new IllegalArgumentException();
+			}
+			this.sequence = sequence;
+		}
+	}
+
+	/**
+	 * Set's whether the image should be visible on the map or not.
+	 *
+	 * @param visible
+	 *            true if the image is set to be visible; false otherwise.
+	 */
+	public void setVisible(final boolean visible) {
+		this.visible = visible;
+	}
+
+	/**
+	 * Called when the mouse button is released, meaning that the picture has
+	 * stopped being dragged, so the temporal values are saved.
+	 */
+	public void stopMoving() {
+		tempLatLon = movingLatLon;
+		tempHe = movingHe;
+	}
+
+	/**
+	 * Turns the image direction.
+	 *
+	 * @param ca
+	 *            The angle the image is moving.
+	 */
+	public void turn(final double ca) {
+		movingHe = tempHe + ca;
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideCubemap.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideCubemap.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideCubemap.java	(revision 34317)
@@ -0,0 +1,141 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside;
+
+import java.awt.image.BufferedImage;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils.CubemapFaces;
+
+/**
+ * @author renerr18
+ *
+ *
+ */
+public class StreetsideCubemap extends StreetsideAbstractImage implements Comparable<StreetsideAbstractImage>{
+
+	private static Map<String,Map<String,BufferedImage>> face2TilesMap = new HashMap<String,Map<String,BufferedImage>>();
+
+	/**
+	* If two values for field cd differ by less than EPSILON both values are considered equal.
+	*/
+	@SuppressWarnings("unused")
+	private static final float EPSILON = 1e-5f;
+
+	/**
+	 * Main constructor of the class StreetsideCubemap
+	 *
+	 * @param quadId
+	 *            The Streetside id of the base frontal image of the cubemap
+	 *            in quternary
+	 * @param latLon
+	 *            The latitude and longitude where it is positioned.
+	 * @param he
+	 *            The direction of the images in degrees, meaning 0 north (camera
+	 *            direction is not yet supported in the Streetside plugin).
+	 */
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+	public StreetsideCubemap(String quadId, LatLon latLon, double he) {
+		super(quadId, latLon, he);
+		face2TilesMap = new HashMap();
+
+		EnumSet.allOf(CubemapUtils.CubemapFaces.class).forEach(face -> {
+			face2TilesMap.put(face.getValue(), new HashMap<String, BufferedImage>());
+		});
+
+	}
+
+	/**
+	* Returns a Map object containing a keyset of cubemap face numbers
+	*
+	* {@link CubemapFaces}
+	*
+	* for each cubeface number corresponding map if cubemap tile ids and buffered
+	* cubemap tile imagery is stored until assembly by the CubemapBuilder
+	* @see org.openstreetmap.josm.plugins.streetside.cubemap.CubemapBuilder
+ 	*
+ 	* @return the face2TilesMap
+ 	*/
+	public Map<String, Map<String,BufferedImage>> getFace2TilesMap() {
+		return face2TilesMap;
+	}
+
+	/**
+	 * Comparison method for the StreetsideCubemap object.
+	 *
+	 * @param image
+	 *            - a StreetsideAbstract image object
+	 *
+	 *            StreetsideCubemaps are considered equal if they are associated
+	 *            with the same image id - only one cubemap may be displayed at a
+	 *            time. If the image selection changes, the cubemap changes.
+	 *
+	 * @return result of the hashcode comparison.
+	 * @see org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage
+	 */
+	@Override
+	public int compareTo(StreetsideAbstractImage image) {
+		if (image instanceof StreetsideImage) {
+			return id.compareTo(((StreetsideImage) image).getId());
+		}
+		return hashCode() - image.hashCode();
+	}
+
+	/**
+	 * HashCode StreetsideCubemap object.
+	 *
+	 * @return int hashCode
+	 * @see org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage
+	 */
+    @Override
+	public int hashCode() {
+		return id.hashCode();
+	}
+
+	/**
+	 * stops ImageDisplay WalkAction (not currently supported by Streetside)
+	 *
+	 * @see org.openstreetmap.josm.plugins.streetside.actions.StreetsideWalkAction
+	 */
+	@Override
+	public void stopMoving() {
+		super.stopMoving();
+	}
+
+	/**
+	 * turns ImageDisplay WalkAction (not currently supported by Streetside)
+	 *
+	 * @param he - the direction the camera is facing (heading)
+	 *
+	 * @see org.openstreetmap.josm.plugins.streetside.actions.StreetsideWalkAction
+	 */
+	@Override
+	public void turn(double he) {
+		super.turn(he);
+	}
+
+	/**
+	 * @return the height of an assembled cubemap face for 16-tiled or 4-tiled imagery
+	 *
+	 * @see org.openstreetmap.josm.plugins.streetside.actions.StreetsideWalkAction
+	 */
+	public int getHeight() {
+		return StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get().booleanValue()?1016:510;
+	}
+
+	/**
+	 * resets the faces2TilesMap, emptying it for a new set of cubemap imagery
+	 */
+	public void resetFaces2TileMap() {
+		face2TilesMap = new HashMap<>();
+
+		EnumSet.allOf(CubemapUtils.CubemapFaces.class).forEach(face -> {
+			face2TilesMap.put(face.getValue(), new HashMap<String, BufferedImage>());
+		});
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideData.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideData.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideData.java	(revision 34317)
@@ -0,0 +1,396 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.stream.Collectors;
+
+import org.apache.commons.jcs.access.CacheAccess;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.plugins.streetside.cache.CacheUtils;
+import org.openstreetmap.josm.plugins.streetside.cache.Caches;
+import org.openstreetmap.josm.plugins.streetside.gui.StreetsideMainDialog;
+import org.openstreetmap.josm.plugins.streetside.gui.StreetsideViewerDialog;
+import org.openstreetmap.josm.plugins.streetside.gui.imageinfo.ImageInfoPanel;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+
+/**
+ * Database class for all the {@link StreetsideAbstractImage} objects.
+ *
+ * @author nokutu
+ * @author renerr18 (extended for Streetside)
+ * @see StreetsideAbstractImage
+ * @see StreetsideSequence
+ */
+public class StreetsideData {
+  private final Set<StreetsideAbstractImage> images = ConcurrentHashMap.newKeySet();
+  /**
+   * The image currently selected, this is the one being shown.
+   */
+  private StreetsideAbstractImage selectedImage;
+  /**
+   * The image under the cursor.
+   */
+  private StreetsideAbstractImage highlightedImage;
+  /**
+   * All the images selected, can be more than one.
+   */
+  private final Set<StreetsideAbstractImage> multiSelectedImages = ConcurrentHashMap.newKeySet();
+  /**
+   * Listeners of the class.
+   */
+  private final List<StreetsideDataListener> listeners = new CopyOnWriteArrayList<>();
+  /**
+   * The bounds of the areas for which the pictures have been downloaded.
+   */
+  private final List<Bounds> bounds;
+
+  /**
+   * Creates a new object and adds the initial set of listeners.
+   */
+  protected StreetsideData() {
+    selectedImage = null;
+    bounds = new CopyOnWriteArrayList<>();
+
+  // Adds the basic set of listeners.
+  Arrays.stream(StreetsidePlugin.getStreetsideDataListeners()).forEach(this::addListener);
+    if (Main.main != null) {
+      addListener(StreetsideMainDialog.getInstance());
+      addListener(ImageInfoPanel.getInstance());
+      addListener(StreetsideViewerDialog.getInstance().getStreetsideViewerPanel());
+    }
+  }
+
+  /**
+   * Adds an StreetsideImage to the object, and then repaints mapView.
+   *
+   * @param image The image to be added.
+   */
+  public void add(StreetsideAbstractImage image) {
+    add(image, true);
+  }
+
+  /**
+   * Adds a StreetsideImage to the object, but doesn't repaint mapView. This is
+   * needed for concurrency.
+   *
+   * @param image  The image to be added.
+   * @param update Whether the map must be updated or not
+   *        (updates are currently unsupported by Streetside).
+   */
+  public void add(StreetsideAbstractImage image, boolean update) {
+    	images.add(image);
+    	if (update) {
+    		StreetsideLayer.invalidateInstance();
+    	}
+    	fireImagesAdded();
+  }
+
+  /**
+   * Adds a set of StreetsideImages to the object, and then repaints mapView.
+   *
+   * @param images The set of images to be added.
+   */
+  public void addAll(Collection<? extends StreetsideAbstractImage> images) {
+    addAll(images, true);
+  }
+
+  /**
+   * Adds a set of {link StreetsideAbstractImage} objects to this object.
+   *
+   * @param newImages The set of images to be added.
+   * @param update Whether the map must be updated or not.
+   */
+  public void addAll(Collection<? extends StreetsideAbstractImage> newImages, boolean update) {
+    images.addAll(newImages);
+    if (update) {
+      StreetsideLayer.invalidateInstance();
+    }
+    fireImagesAdded();
+  }
+
+ /**
+   * Adds a new listener.
+   *
+   * @param lis Listener to be added.
+   */
+  public final void addListener(final StreetsideDataListener lis) {
+    listeners.add(lis);
+  }
+
+  /**
+   * Adds a {@link StreetsideImage} object to the list of selected images, (when
+   * ctrl + click)
+   *
+   * @param image The {@link StreetsideImage} object to be added.
+   */
+  public void addMultiSelectedImage(final StreetsideAbstractImage image) {
+    if (!multiSelectedImages.contains(image)) {
+      if (getSelectedImage() == null) {
+        this.setSelectedImage(image);
+      } else {
+        multiSelectedImages.add(image);
+      }
+    }
+    StreetsideLayer.invalidateInstance();
+  }
+
+  /**
+   * Adds a set of {@code StreetsideAbstractImage} objects to the list of
+   * selected images.
+   *
+   * @param images A {@link Collection} object containing the set of images to be added.
+   */
+  public void addMultiSelectedImage(Collection<StreetsideAbstractImage> images) {
+    images.stream().filter(image -> !multiSelectedImages.contains(image)).forEach(image -> {
+      if (getSelectedImage() == null) {
+        this.setSelectedImage(image);
+      } else {
+        multiSelectedImages.add(image);
+      }
+    });
+    StreetsideLayer.invalidateInstance();
+  }
+
+  public List<Bounds> getBounds() {
+    return bounds;
+  }
+
+  /**
+   * Removes a listener.
+   *
+   * @param lis Listener to be removed.
+   */
+  public void removeListener(StreetsideDataListener lis) {
+    listeners.remove(lis);
+  }
+
+  /**
+   * Highlights the image under the cursor.
+   *
+   * @param image The image under the cursor.
+   */
+  public void setHighlightedImage(StreetsideAbstractImage image) {
+    highlightedImage = image;
+  }
+
+  /**
+   * Returns the image under the mouse cursor.
+   *
+   * @return The image under the mouse cursor.
+   */
+  public StreetsideAbstractImage getHighlightedImage() {
+    return highlightedImage;
+  }
+
+  /**
+   * Returns a Set containing all images.
+   *
+   * @return A Set object containing all images.
+   */
+  public Set<StreetsideAbstractImage> getImages() {
+    return images;
+  }
+
+  /**
+   * Returns a Set of all sequences, that the images are part of.
+   * @return all sequences that are contained in the Streetside data
+   */
+  public Set<StreetsideSequence> getSequences() {
+    return images.stream().map(StreetsideAbstractImage::getSequence).collect(Collectors.toSet());
+  }
+
+  /**
+   * Returns the StreetsideImage object that is currently selected.
+   *
+   * @return The selected StreetsideImage object.
+   */
+  public StreetsideAbstractImage getSelectedImage() {
+    return selectedImage;
+  }
+
+  private void fireImagesAdded() {
+    listeners.stream().filter(Objects::nonNull).forEach(StreetsideDataListener::imagesAdded);
+  }
+
+  /**
+   * If the selected StreetsideImage is part of a StreetsideSequence then the
+   * following visible StreetsideImage is selected. In case there is none, does
+   * nothing.
+   *
+   * @throws IllegalStateException if the selected image is null or the selected image doesn't
+   *                               belong to a sequence.
+   */
+  public void selectNext() {
+    selectNext(StreetsideProperties.MOVE_TO_IMG.get());
+  }
+
+  /**
+   * If the selected StreetsideImage is part of a StreetsideSequence then the
+   * following visible StreetsideImage is selected. In case there is none, does
+   * nothing.
+   *
+   * @param moveToPicture True if the view must me moved to the next picture.
+   * @throws IllegalStateException if the selected image is null or the selected image doesn't
+   *                               belong to a sequence.
+   */
+  public void selectNext(boolean moveToPicture) {
+    if (getSelectedImage() == null) {
+		throw new IllegalStateException();
+	}
+    if (getSelectedImage().getSequence() == null) {
+		throw new IllegalStateException();
+	}
+    StreetsideAbstractImage tempImage = selectedImage;
+    while (tempImage.next() != null) {
+      tempImage = tempImage.next();
+      if (tempImage.isVisible()) {
+        setSelectedImage(tempImage, moveToPicture);
+        break;
+      }
+    }
+  }
+
+  /**
+   * If the selected StreetsideImage is part of a StreetsideSequence then the
+   * previous visible StreetsideImage is selected. In case there is none, does
+   * nothing.
+   *
+   * @throws IllegalStateException if the selected image is null or the selected image doesn't
+   *                               belong to a sequence.
+   */
+  public void selectPrevious() {
+    selectPrevious(StreetsideProperties.MOVE_TO_IMG.get());
+  }
+
+  /**
+   * If the selected StreetsideImage is part of a StreetsideSequence then the
+   * previous visible StreetsideImage is selected. In case there is none, does
+   * nothing. * @throws IllegalStateException if the selected image is null or
+   * the selected image doesn't belong to a sequence.
+   *
+   * @param moveToPicture True if the view must me moved to the previous picture.
+   * @throws IllegalStateException if the selected image is null or the selected image doesn't
+   *                               belong to a sequence.
+   */
+  public void selectPrevious(boolean moveToPicture) {
+    if (getSelectedImage() == null) {
+		throw new IllegalStateException();
+	}
+    if (getSelectedImage().getSequence() == null) {
+		throw new IllegalStateException();
+	}
+    StreetsideAbstractImage tempImage = selectedImage;
+    while (tempImage.previous() != null) {
+      tempImage = tempImage.previous();
+      if (tempImage.isVisible()) {
+        setSelectedImage(tempImage, moveToPicture);
+        break;
+      }
+    }
+  }
+
+  /**
+   * Selects a new image.If the user does ctrl + click, this isn't triggered.
+   *
+   * @param image The StreetsideImage which is going to be selected
+   */
+  public void setSelectedImage(StreetsideAbstractImage image) {
+    setSelectedImage(image, false);
+  }
+
+  /**
+   * Selects a new image.If the user does ctrl+click, this isn't triggered. You
+   * can choose whether to center the view on the new image or not.
+   *
+   * @param image The {@link StreetsideImage} which is going to be selected.
+   * @param zoom  True if the view must be centered on the image; false otherwise.
+   */
+  public void setSelectedImage(StreetsideAbstractImage image, boolean zoom) {
+    StreetsideAbstractImage oldImage = selectedImage;
+    selectedImage = image;
+    multiSelectedImages.clear();
+    final MapView mv = StreetsidePlugin.getMapView();
+    if (image != null) {
+      multiSelectedImages.add(image);
+      if (mv != null && image instanceof StreetsideImage) {
+        StreetsideImage streetsideImage = (StreetsideImage) image;
+
+        // Downloading thumbnails of surrounding pictures.
+        StreetsideData.downloadSurroundingImages(streetsideImage);
+      }
+    }
+    if (mv != null && zoom && selectedImage != null) {
+      mv.zoomTo(selectedImage.getMovingLatLon());
+    }
+    fireSelectedImageChanged(oldImage, selectedImage);
+    StreetsideLayer.invalidateInstance();
+  }
+
+  /**
+   * Downloads surrounding images of this mapillary image in background threads
+   * @param streetsideImage the image for which the surrounding images should be downloaded
+   */
+  private static void downloadSurroundingImages (StreetsideImage streetsideImage) {
+    MainApplication.worker.execute(() -> {
+      final int prefetchCount = StreetsideProperties.PRE_FETCH_IMAGE_COUNT.get();
+      CacheAccess <String, BufferedImageCacheEntry> imageCache = Caches.ImageCache.getInstance().getCache();
+
+      StreetsideAbstractImage nextImage = streetsideImage.next();
+      StreetsideAbstractImage prevImage = streetsideImage.previous();
+
+      for (int i = 0; i < prefetchCount; i++) {
+        if (nextImage != null) {
+          if (nextImage instanceof StreetsideImage &&
+            imageCache.get(((StreetsideImage) nextImage).getId()) == null) {
+            CacheUtils.downloadPicture((StreetsideImage) nextImage);
+          }
+          nextImage = nextImage.next();
+        }
+        if (prevImage != null) {
+          if (prevImage instanceof StreetsideImage &&
+            imageCache.get(((StreetsideImage) prevImage).getId()) == null) {
+            CacheUtils.downloadPicture((StreetsideImage) prevImage);
+          }
+          prevImage = prevImage.previous();
+        }
+      }
+    });
+  }
+
+  private void fireSelectedImageChanged(StreetsideAbstractImage oldImage, StreetsideAbstractImage newImage) {
+	listeners.stream().filter(Objects::nonNull).forEach(lis -> lis.selectedImageChanged(oldImage, newImage));
+  }
+
+  /**
+   * Returns a List containing all {@code StreetsideAbstractImage} objects
+   * selected with ctrl + click.
+   *
+   * @return A List object containing all the images selected.
+   */
+  public Set<StreetsideAbstractImage> getMultiSelectedImages() {
+    return multiSelectedImages;
+  }
+
+  /**
+   * Sets a new {@link Collection} object as the used set of images.
+   * Any images that are already present, are removed.
+   *
+   * @param newImages the new image list (previously set images are completely replaced)
+   */
+  public void setImages(Collection<StreetsideAbstractImage> newImages) {
+    synchronized (this) {
+      images.clear();
+      images.addAll(newImages);
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideDataListener.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideDataListener.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideDataListener.java	(revision 34317)
@@ -0,0 +1,28 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside;
+
+/**
+ * Interface for listeners of the class {@link StreetsideData}.
+ *
+ * @author nokutu
+ *
+ */
+public interface StreetsideDataListener {
+
+  /**
+   * Fired when any image is added to the database.
+   */
+  void imagesAdded();
+
+  /**
+   * Fired when the selected image is changed by something different from
+   * manually clicking on the icon.
+   *
+   * @param oldImage
+   *          Old selected {@link StreetsideAbstractImage}
+   * @param newImage
+   *          New selected {@link StreetsideAbstractImage}
+   */
+  void selectedImageChanged(StreetsideAbstractImage oldImage,
+      StreetsideAbstractImage newImage);
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideImage.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideImage.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideImage.java	(revision 34317)
@@ -0,0 +1,360 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside;
+
+import java.util.List;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
+import org.openstreetmap.josm.plugins.streetside.model.UserProfile;
+
+/**
+ * A StreetsideImage object represents each of the images stored in Streetside.
+ *
+ * @author nokutu
+ * @author renerr18
+ *
+ * @see StreetsideSequence
+ * @see StreetsideData
+ */
+public class StreetsideImage extends StreetsideAbstractImage {
+  /**
+   * Rn is a Bing Streetside image attribute - currently not
+   * used, mapped or supported in the Streetside plugin -
+   * left out initially because it's an unrequired complex object.
+   */
+  public static class Rn {
+	  // placeholder for nexted Rn attribute
+  }
+
+  // latitude of the Streetside image
+  private double la;
+
+  //longitude of the Streetside image
+  private double lo;
+
+  // The bubble altitude, in meters above the WGS84 ellipsoid
+  private double al;
+
+  // Roll
+  private double ro;
+
+  // Pitch
+  private double pi;
+
+  // Heading (equivalent to Mapillary cd attribute - not currently supported.
+  private double he;
+
+  // Blurring instructions - not currently used by the plugin
+  private String bl;
+
+  // Undocumented Attributes
+  private int ml;
+  private long ne;
+  private long pr;
+  private List<String> nbn;
+  private List<String> pbn;
+  private int ad;
+  private Rn rn;
+
+  /**
+   * Set of traffic signs in the image.
+   *//*
+  private final List<ImageDetection> detections = Collections.synchronizedList(new ArrayList<>());
+*/
+  /**
+   * Main constructor of the class StreetsideImage
+   *
+   * @param key    The unique identifier of the image.
+   * @param latLon The latitude and longitude where it is positioned.
+   * @param cd     The direction of the images in degrees, meaning 0 north.
+   */
+
+  public StreetsideImage(String id, LatLon latLon, double he) {
+    super(id, latLon, he);
+  }
+
+  public StreetsideImage(String id, LatLon latLon) {
+    super(id, latLon, 0.0);
+  }
+
+  public StreetsideImage(String id, double la, double lo) {
+    super(id, new LatLon(la,lo), 0.0);
+  }
+
+  public StreetsideImage(String id) {
+	    super(id);
+  }
+
+  // Default constructor for Jackson/JSON Deserializattion
+  public StreetsideImage() {
+    super(CubemapUtils.IMPORTED_ID, null, 0.0);
+  }
+
+  /**
+   * Returns the unique identifier of the object.
+   *
+   * @return A {@code String} containing the unique identifier of the object.
+   */
+  @Override
+public String getId() {
+    return String.valueOf(id);
+  }
+
+  /*public List<ImageDetection> getDetections() {
+    return detections;
+  }*/
+
+  /*public void setAllDetections(Collection<ImageDetection> newDetections) {
+    Logging.debug("Add {0} detections to image {1}", newDetections.size(), getId());
+    synchronized (detections) {
+      detections.clear();
+      detections.addAll(newDetections);
+    }
+  }*/
+
+  public UserProfile getUser() {
+	    return getSequence().getUser();
+  }
+
+  @Override
+  public String toString() {
+    return String.format(
+      // TODO: format date cd (Gradle build error command line)
+      "Image[id=%s,lat=%f,lon=%f,he=%f,user=%s]",
+      id, latLon.lat(), latLon.lon(), he, "null"//, cd
+    );
+  }
+
+  // TODO: implement equals @rrh
+  @Override
+  public boolean equals(Object object) {
+    return object instanceof StreetsideImage && id.equals(((StreetsideImage) object).getId());
+  }
+
+  // TODO: implement compareTo @rrh
+  @Override
+  public int compareTo(StreetsideAbstractImage image) {
+    if (image instanceof StreetsideImage) {
+      return id.compareTo(((StreetsideImage) image).getId());
+    }
+    return hashCode() - image.hashCode();
+  }
+
+  // TODO: implement hashcode @rrh
+  @Override
+  public int hashCode() {
+    return id.hashCode();
+  }
+
+  @Override
+  public void stopMoving() {
+    super.stopMoving();
+    checkModified();
+  }
+
+  private void checkModified() {
+    if (StreetsideLayer.hasInstance()) {
+      if (isModified()) {
+        StreetsideLayer.getInstance().getLocationChangeset().add(this);
+      } else {
+        StreetsideLayer.getInstance().getLocationChangeset().remove(this);
+      }
+    }
+  }
+
+  @Override
+  public void turn(double ca) {
+    super.turn(ca);
+    checkModified();
+  }
+
+  /**
+   * @return the altitude
+   */
+  public double getAl() {
+    return al;
+  }
+
+  /**
+   * @param altitude the altitude to set
+   */
+  public void setAl(double altitude) {
+    al = altitude;
+  }
+
+  /**
+   * @return the roll
+   */
+  public double getRo() {
+    return ro;
+  }
+
+  /**
+   * @param roll the roll to set
+   */
+  public void setRo(double roll) {
+    ro = roll;
+  }
+
+  /**
+   * @return the pi
+   */
+  public double getPi() {
+    return pi;
+  }
+
+  /**
+   * @param pi the pi to set
+   */
+  public void setPi(double pitch) {
+    pi = pitch;
+  }
+
+  /**
+   * @return the burringl
+   */
+  public String getBl() {
+    return bl;
+  }
+
+  /**
+   * @param burringl the burringl to set
+   */
+  public void setBl(String blurring) {
+    bl = blurring;
+  }
+
+  /**
+   * @return the ml
+   */
+  public int getMl() {
+    return ml;
+  }
+
+  /**
+   * @param ml the ml to set
+   */
+  public void setMl(int ml) {
+    this.ml = ml;
+  }
+
+  /**
+   * @return the ne
+   */
+  public long getNe() {
+    return ne;
+  }
+
+  /**
+   * @param ne the ne to set
+   */
+  public void setNe(long ne) {
+    this.ne = ne;
+  }
+
+  /**
+   * @return the pr
+   */
+  public long getPr() {
+    return pr;
+  }
+
+  /**
+   * @param pr the pr to set
+   */
+  public void setPr(long pr) {
+    this.pr = pr;
+  }
+
+  /**
+   * @return the nbn
+   */
+  public List<String> getNbn() {
+    return nbn;
+  }
+
+  /**
+   * @param nbn the nbn to set
+   */
+  public void setNbn(List<String> nbn) {
+    this.nbn = nbn;
+  }
+
+  /**
+   * @return the pbn
+   */
+  public List<String> getPbn() {
+    return pbn;
+  }
+
+  /**
+   * @param pbn the pbn to set
+   */
+  public void setPbn(List<String> pbn) {
+    this.pbn = pbn;
+  }
+
+  /**
+   * @return the ad
+   */
+  public int getAd() {
+    return ad;
+  }
+
+  /**
+   * @param ad the ad to set
+   */
+  public void setAd(int ad) {
+    this.ad = ad;
+  }
+
+  /**
+   * @return the la
+   */
+  public double getLa() {
+    return la;
+  }
+
+  /**
+   * @param la the la to set
+   */
+  public void setLa(double la) {
+    this.la = la;
+  }
+
+  /**
+   * @return the lo
+   */
+  public double getLo() {
+    return lo;
+  }
+
+  /**
+   * @param lo the lo to set
+   */
+  public void setLo(double lo) {
+    this.lo = lo;
+  }
+
+  /**
+   * @param id the id to set
+   */
+  @Override
+public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * @return the rn
+   */
+  public Rn getRn() {
+    return rn;
+  }
+
+  /**
+   * @param rn the rn to set
+   */
+  public void setRn(Rn rn) {
+    this.rn = rn;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideImportedImage.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideImportedImage.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideImportedImage.java	(revision 34317)
@@ -0,0 +1,158 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.text.ParseException;
+import java.util.Calendar;
+
+import javax.imageio.ImageIO;
+
+import org.openstreetmap.josm.data.coor.CachedLatLon;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
+import org.openstreetmap.josm.gui.layer.geoimage.ImageEntry;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideUtils;
+
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
+
+/**
+ * A StreetsideImoprtedImage object represents a picture imported locally.
+ *
+ * @author nokutu
+ *
+ */
+public class StreetsideImportedImage extends StreetsideAbstractImage {
+
+  /** The picture file. */
+  protected File file;
+
+  /**
+   * Creates a new StreetsideImportedImage object using as date the current date.
+   * Using when the EXIF tags doesn't contain that info.
+   *
+   * @param latLon  The latitude and longitude where the picture was taken.
+   * @param cd  Direction of the picture (0 means north).
+   * @param file  The file containing the picture.
+   */
+  public StreetsideImportedImage(final String id, final LatLon latLon, final double ca, final File file) {
+    this(id, latLon, ca, file, Calendar.getInstance().getTimeInMillis());
+  }
+
+  /**
+   * Main constructor of the class.
+   *
+   * @param latLon  Latitude and Longitude where the picture was taken.
+   * @param cd  Direction of the picture (0 means north),
+   * @param file  The file containing the picture.
+   * @param datetimeOriginal  The date the picture was taken.
+   */
+  public StreetsideImportedImage(final String id, final LatLon latLon, final double ca, final File file, final String datetimeOriginal) {
+    this(id, latLon, ca, file, parseTimestampElseCurrentTime(datetimeOriginal));
+  }
+
+  /**
+   * Constructs a new image from an image entry of a {@link GeoImageLayer}.
+   * @param geoImage the {@link ImageEntry}, from which the corresponding fields are taken
+   * @return new image
+   */
+  public static StreetsideImportedImage createInstance(final ImageEntry geoImage) {
+    if (geoImage == null) {
+      return null;
+    }
+    if (geoImage.getFile() == null) {
+      throw new IllegalArgumentException("Can't create an imported image from an ImageEntry without associated file.");
+    }
+    final CachedLatLon cachedCoord = geoImage.getPos();
+    LatLon coord = cachedCoord == null ? null : cachedCoord.getRoundedToOsmPrecision();
+    if (coord == null) {
+      final MapView mv = StreetsidePlugin.getMapView();
+      coord = mv == null ? new LatLon(0, 0) : mv.getProjection().eastNorth2latlon(mv.getCenter());
+    }
+    final double ca = geoImage.getExifImgDir() == null ? 0 : geoImage.getExifImgDir();
+    final long time = geoImage.hasGpsTime()
+      ? geoImage.getGpsTime().getTime()
+      : geoImage.hasExifTime() ? geoImage.getExifTime().getTime() : System.currentTimeMillis();
+    return new StreetsideImportedImage(CubemapUtils.IMPORTED_ID, coord, ca, geoImage.getFile(), time);
+  }
+
+  private static long parseTimestampElseCurrentTime(final String timestamp) {
+    try {
+      return StreetsideUtils.getEpoch(timestamp, "yyyy:MM:dd HH:mm:ss");
+    } catch (ParseException e) {
+      try {
+        return StreetsideUtils.getEpoch(timestamp, "yyyy/MM/dd HH:mm:ss");
+      } catch (ParseException e1) {
+        return StreetsideUtils.currentTime();
+      }
+    }
+  }
+
+  public StreetsideImportedImage(final String id, final LatLon latLon, final double he, final File file, final long ca) {
+    super(id, latLon, he);
+    this.file = file;
+    this.cd = ca;
+  }
+
+  /**
+   * Returns the pictures of the file.
+   *
+   * @return A {@link BufferedImage} object containing the picture, or null if
+   *         the {@link File} given in the constructor was null.
+   * @throws IOException
+   *           If the file parameter of the object isn't an image.
+   */
+  public BufferedImage getImage() throws IOException {
+    if (file != null)
+      return ImageIO.read(file);
+    return null;
+  }
+
+  /**
+   * Returns the {@link File} object where the picture is located.
+   *
+   * @return The {@link File} object where the picture is located.
+   */
+  public File getFile() {
+    return file;
+  }
+
+  @Override
+  public int compareTo(StreetsideAbstractImage image) {
+    if (image instanceof StreetsideImportedImage)
+      return file.compareTo(((StreetsideImportedImage) image).getFile());
+    return hashCode() - image.hashCode();
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((file == null) ? 0 : file.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (!(obj instanceof StreetsideImportedImage)) {
+      return false;
+    }
+    StreetsideImportedImage other = (StreetsideImportedImage) obj;
+    if (file == null) {
+      if (other.file != null) {
+        return false;
+      }
+    } else if (!file.equals(other.file)) {
+      return false;
+    }
+    return true;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideLayer.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideLayer.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideLayer.java	(revision 34317)
@@ -0,0 +1,612 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside;
+
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.TexturePaint;
+import java.awt.geom.Line2D;
+import java.awt.image.BufferedImage;
+import java.util.Comparator;
+import java.util.IntSummaryStatistics;
+import java.util.Optional;
+
+import javax.swing.Action;
+import javax.swing.Icon;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.event.DataChangedEvent;
+import org.openstreetmap.josm.data.osm.event.DataSetListenerAdapter;
+import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.NavigatableComponent;
+import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
+import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
+import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.LayerManager;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
+import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
+import org.openstreetmap.josm.plugins.streetside.cache.CacheUtils;
+import org.openstreetmap.josm.plugins.streetside.gui.StreetsideMainDialog;
+import org.openstreetmap.josm.plugins.streetside.history.StreetsideRecord;
+import org.openstreetmap.josm.plugins.streetside.io.download.StreetsideDownloader;
+import org.openstreetmap.josm.plugins.streetside.io.download.StreetsideDownloader.DOWNLOAD_MODE;
+import org.openstreetmap.josm.plugins.streetside.mode.AbstractMode;
+import org.openstreetmap.josm.plugins.streetside.mode.JoinMode;
+import org.openstreetmap.josm.plugins.streetside.mode.SelectMode;
+import org.openstreetmap.josm.plugins.streetside.utils.MapViewGeometryUtil;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideColorScheme;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideUtils;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
+
+/**
+ * This class represents the layer shown in JOSM. There can only exist one
+ * instance of this object.
+ *
+ * @author nokutu
+ */
+public final class StreetsideLayer extends AbstractModifiableLayer implements
+ActiveLayerChangeListener, StreetsideDataListener {
+
+	/** The radius of the image marker */
+	private static final int IMG_MARKER_RADIUS = 7;
+	/** The radius of the circular sector that indicates the camera angle */
+	private static final int CA_INDICATOR_RADIUS = 15;
+	/** The angle of the circular sector that indicates the camera angle */
+	private static final int CA_INDICATOR_ANGLE = 40;
+	/** Length of the edge of the small sign, which indicates that traffic signs have been found in an image. */
+	private static final int TRAFFIC_SIGN_SIZE = 6;
+	/** A third of the height of the sign, for easier calculations */
+	private static final double TRAFFIC_SIGN_HEIGHT_3RD = Math.sqrt(
+			Math.pow(StreetsideLayer.TRAFFIC_SIGN_SIZE, 2) - Math.pow(StreetsideLayer.TRAFFIC_SIGN_SIZE / 2d, 2)
+			) / 3;
+
+	private static final DataSetListenerAdapter DATASET_LISTENER =
+			new DataSetListenerAdapter(e -> {
+				if (e instanceof DataChangedEvent && StreetsideDownloader.getMode() == DOWNLOAD_MODE.OSM_AREA) {
+					// When more data is downloaded, a delayed update is thrown, in order to
+					// wait for the data bounds to be set.
+					MainApplication.worker.execute(StreetsideDownloader::downloadOSMArea);
+				}
+			});
+
+	/** Unique instance of the class. */
+	private static StreetsideLayer instance;
+	/** The nearest images to the selected image from different sequences sorted by distance from selection. */
+	private StreetsideImage[] nearestImages = {};
+	/** {@link StreetsideData} object that stores the database. */
+	private final StreetsideData data;
+
+	/** Mode of the layer. */
+	public AbstractMode mode;
+
+	private volatile TexturePaint hatched;
+	private final StreetsideLocationChangeset locationChangeset = new StreetsideLocationChangeset();
+
+	private StreetsideLayer() {
+		super(I18n.tr("Microsoft Streetside Images"));
+		data = new StreetsideData();
+		data.addListener(this);
+	}
+
+	/**
+	 * Initializes the Layer.
+	 */
+	private void init() {
+		final DataSet ds = MainApplication.getLayerManager().getEditDataSet();
+		if (ds != null) {
+			ds.addDataSetListener(StreetsideLayer.DATASET_LISTENER);
+		}
+		MainApplication.getLayerManager().addLayer(this);
+		MainApplication.getLayerManager().addActiveLayerChangeListener(this);
+		if (!GraphicsEnvironment.isHeadless()) {
+			setMode(new SelectMode());
+			if (StreetsideDownloader.getMode() == DOWNLOAD_MODE.OSM_AREA) {
+				StreetsideDownloader.downloadOSMArea();
+			}
+			if (StreetsideDownloader.getMode() == DOWNLOAD_MODE.VISIBLE_AREA) {
+				mode.zoomChanged();
+			}
+		}
+		// Does not execute when in headless mode
+		if (Main.main != null && !StreetsideMainDialog.getInstance().isShowing()) {
+			StreetsideMainDialog.getInstance().showDialog();
+		}
+		if (StreetsidePlugin.getMapView() != null) {
+			StreetsideMainDialog.getInstance().getStreetsideImageDisplay().repaint();
+
+			// There is no delete image action for Streetside (Mapillary functionality here removed).
+
+			//getLocationChangeset().addChangesetListener(StreetsideChangesetDialog.getInstance());
+		}
+		createHatchTexture();
+		invalidate();
+	}
+
+	public static void invalidateInstance() {
+		if (StreetsideLayer.hasInstance()) {
+			StreetsideLayer.getInstance().invalidate();
+		}
+	}
+
+	/**
+	 * Changes the mode the the given one.
+	 *
+	 * @param mode The mode that is going to be activated.
+	 */
+	public void setMode(AbstractMode mode) {
+		final MapView mv = StreetsidePlugin.getMapView();
+		if (this.mode != null && mv != null) {
+			mv.removeMouseListener(this.mode);
+			mv.removeMouseMotionListener(this.mode);
+			NavigatableComponent.removeZoomChangeListener(this.mode);
+		}
+		this.mode = mode;
+		if (mode != null && mv != null) {
+			mv.setNewCursor(mode.cursor, this);
+			mv.addMouseListener(mode);
+			mv.addMouseMotionListener(mode);
+			NavigatableComponent.addZoomChangeListener(mode);
+			StreetsideUtils.updateHelpText();
+		}
+	}
+
+	private static synchronized void clearInstance() {
+		StreetsideLayer.instance = null;
+	}
+
+	/**
+	 * Returns the unique instance of this class.
+	 *
+	 * @return The unique instance of this class.
+	 */
+	public static synchronized StreetsideLayer getInstance() {
+		if (StreetsideLayer.instance != null) {
+			if (!MainApplication.getLayerManager().containsLayer(StreetsideLayer.instance)) {
+				MainApplication.getLayerManager().addLayer(StreetsideLayer.instance);
+			}
+			return StreetsideLayer.instance;
+		}
+		final StreetsideLayer layer = new StreetsideLayer();
+		StreetsideLayer.instance = layer;
+		layer.init();
+		return layer;
+	}
+
+	/**
+	 * @return if the unique instance of this layer is currently instantiated and added to the {@link LayerManager}
+	 */
+	public static boolean hasInstance() {
+		return StreetsideLayer.instance != null && MainApplication.getLayerManager().containsLayer(StreetsideLayer.instance);
+	}
+
+	/**
+	 * Returns the {@link StreetsideData} object, which acts as the database of the
+	 * Layer.
+	 *
+	 * @return The {@link StreetsideData} object that stores the database.
+	 */
+	public StreetsideData getData() {
+		return data;
+	}
+
+	/**
+	 * Returns the n-nearest image, for n=1 the nearest one is returned, for n=2 the second nearest one and so on.
+	 * The "n-nearest image" is picked from the list of one image from every sequence that is nearest to the currently
+	 * selected image, excluding the sequence to which the selected image belongs.
+	 * @param n the index for picking from the list of "nearest images", beginning from 1
+	 * @return the n-nearest image to the currently selected image
+	 */
+	public synchronized StreetsideImage getNNearestImage(final int n) {
+		return n >= 1 && n <= nearestImages.length ? nearestImages[n - 1] : null;
+	}
+
+	/**
+	   * Returns the {@link StreetsideLocationChangeset} object, which acts as the database of the
+	   * Layer.
+	   *
+	   * @return The {@link MapillaryData} object that stores the database.
+	   */
+	  public StreetsideLocationChangeset getLocationChangeset() {
+	    return locationChangeset;
+	  }
+
+
+	@Override
+	public synchronized void destroy() {
+		// TODO: Add destroy code for CubemapBuilder, et al.? @rrh
+		StreetsideLayer.clearInstance();
+		setMode(null);
+		StreetsideRecord.getInstance().reset();
+		AbstractMode.resetThread();
+		StreetsideDownloader.stopAll();
+		if (StreetsideMainDialog.hasInstance()) {
+			StreetsideMainDialog.getInstance().setImage(null);
+			StreetsideMainDialog.getInstance().updateImage();
+		}
+		final MapView mv = StreetsidePlugin.getMapView();
+		if (mv != null) {
+			mv.removeMouseListener(mode);
+			mv.removeMouseMotionListener(mode);
+		}
+		try {
+			MainApplication.getLayerManager().removeActiveLayerChangeListener(this);
+			if (MainApplication.getLayerManager().getEditDataSet() != null) {
+				MainApplication.getLayerManager().getEditDataSet().removeDataSetListener(StreetsideLayer.DATASET_LISTENER);
+			}
+		} catch (final IllegalArgumentException e) {
+			// TODO: It would be ideal, to fix this properly. But for the moment let's catch this, for when a listener has already been removed.
+		}
+		super.destroy();
+	}
+
+	@Override
+	public boolean isModified() {
+		// TODO: Add cubemap modification here? @rrh
+		return data.getImages().parallelStream().anyMatch(StreetsideAbstractImage::isModified);
+	}
+
+	@Override
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+		getData().getImages().parallelStream().forEach(img -> img.setVisible(visible));
+		if (MainApplication.getMap() != null) {
+			//StreetsideFilterDialog.getInstance().refresh();
+		}
+	}
+
+	/**
+	 * Initialize the hatch pattern used to paint the non-downloaded area.
+	 */
+	private void createHatchTexture() {
+		final BufferedImage bi = new BufferedImage(15, 15, BufferedImage.TYPE_INT_ARGB);
+		final Graphics2D big = bi.createGraphics();
+		big.setColor(StreetsideProperties.BACKGROUND.get());
+		final Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
+		big.setComposite(comp);
+		big.fillRect(0, 0, 15, 15);
+		big.setColor(StreetsideProperties.OUTSIDE_DOWNLOADED_AREA.get());
+		big.drawLine(0, 15, 15, 0);
+		final Rectangle r = new Rectangle(0, 0, 15, 15);
+		hatched = new TexturePaint(bi, r);
+	}
+
+	@Override
+	public synchronized void paint(final Graphics2D g, final MapView mv, final Bounds box) {
+		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+		if (MainApplication.getLayerManager().getActiveLayer() == this) {
+			// paint remainder
+			g.setPaint(hatched);
+			g.fill(MapViewGeometryUtil.getNonDownloadedArea(mv, data.getBounds()));
+		}
+
+		// Draw the blue and red line
+		synchronized (StreetsideLayer.class) {
+			final StreetsideAbstractImage selectedImg = data.getSelectedImage();
+			for (int i = 0; i < nearestImages.length && selectedImg != null; i++) {
+				if (i == 0) {
+					g.setColor(Color.RED);
+				} else {
+					g.setColor(Color.BLUE);
+				}
+				final Point selected = mv.getPoint(selectedImg.getMovingLatLon());
+				final Point p = mv.getPoint(nearestImages[i].getMovingLatLon());
+				g.draw(new Line2D.Double(p.getX(), p.getY(), selected.getX(), selected.getY()));
+			}
+		}
+
+		// Draw sequence line
+		g.setStroke(new BasicStroke(2));
+		final StreetsideAbstractImage selectedImage = getData().getSelectedImage();
+		for (final StreetsideSequence seq : getData().getSequences()) {
+			if (seq.getImages().contains(selectedImage)) {
+				g.setColor(
+						seq.getId() == null ? StreetsideColorScheme.SEQ_IMPORTED_SELECTED : StreetsideColorScheme.SEQ_SELECTED
+						);
+			} else {
+				g.setColor(
+						seq.getId() == null ? StreetsideColorScheme.SEQ_IMPORTED_UNSELECTED : StreetsideColorScheme.SEQ_UNSELECTED
+						);
+			}
+			g.draw(MapViewGeometryUtil.getSequencePath(mv, seq));
+		}
+		/*for (final StreetsideAbstractImage imageAbs : data.getImages()) {
+			if (imageAbs.isVisible() && mv != null && mv.contains(mv.getPoint(imageAbs.getMovingLatLon()))) {
+				drawImageMarker(g, imageAbs);
+			}
+		}*/
+		if (mode instanceof JoinMode) {
+			mode.paint(g, mv, box);
+		}
+	}
+
+	/**
+	 * Draws an image marker onto the given Graphics context.
+	 * @param g the Graphics context
+	 * @param img the image to be drawn onto the Graphics context
+	 */
+	/*private void drawImageMarker(final Graphics2D g, final StreetsideAbstractImage img) {
+		if (img == null || img.getLatLon() == null) {
+			Logging.warn("An image is not painted, because it is null or has no LatLon!");
+			return;
+		}
+		final StreetsideAbstractImage selectedImg = getData().getSelectedImage();
+		final Point p = MainApplication.getMap().mapView.getPoint(img.getMovingLatLon());
+
+		// Determine colors
+		final Color markerC;
+		final Color directionC;
+		if (selectedImg != null && getData().getMultiSelectedImages().contains(img)) {
+			markerC = img instanceof StreetsideImportedImage
+					? StreetsideColorScheme.SEQ_IMPORTED_HIGHLIGHTED
+							: StreetsideColorScheme.SEQ_HIGHLIGHTED;
+			directionC = img instanceof StreetsideImportedImage
+					? StreetsideColorScheme.SEQ_IMPORTED_HIGHLIGHTED_CA
+							: StreetsideColorScheme.SEQ_HIGHLIGHTED_CA;
+		} else if (selectedImg != null && selectedImg.getSequence() != null && selectedImg.getSequence().equals(img.getSequence())) {
+			markerC = img instanceof StreetsideImportedImage
+					? StreetsideColorScheme.SEQ_IMPORTED_SELECTED
+							: StreetsideColorScheme.SEQ_SELECTED;
+			directionC = img instanceof StreetsideImportedImage
+					? StreetsideColorScheme.SEQ_IMPORTED_SELECTED_CA
+							: StreetsideColorScheme.SEQ_SELECTED_CA;
+		} else {
+			markerC = img instanceof StreetsideImportedImage
+					? StreetsideColorScheme.SEQ_IMPORTED_UNSELECTED
+							: StreetsideColorScheme.SEQ_UNSELECTED;
+			directionC = img instanceof StreetsideImportedImage
+					? StreetsideColorScheme.SEQ_IMPORTED_UNSELECTED_CA
+							: StreetsideColorScheme.SEQ_UNSELECTED_CA;
+		}
+
+		// Paint direction indicator
+		g.setColor(directionC);
+		g.fillArc(p.x - StreetsideLayer.CA_INDICATOR_RADIUS, p.y - StreetsideLayer.CA_INDICATOR_RADIUS, 2 * StreetsideLayer.CA_INDICATOR_RADIUS, 2 * StreetsideLayer.CA_INDICATOR_RADIUS, (int) (90 - img.getMovingHe() - StreetsideLayer.CA_INDICATOR_ANGLE / 2d), StreetsideLayer.CA_INDICATOR_ANGLE);
+		// Paint image marker
+		g.setColor(markerC);
+		g.fillOval(p.x - StreetsideLayer.IMG_MARKER_RADIUS, p.y - StreetsideLayer.IMG_MARKER_RADIUS, 2 * StreetsideLayer.IMG_MARKER_RADIUS, 2 * StreetsideLayer.IMG_MARKER_RADIUS);
+
+		// Paint highlight for selected or highlighted images
+		if (img.equals(getData().getHighlightedImage()) || getData().getMultiSelectedImages().contains(img)) {
+			g.setColor(Color.WHITE);
+			g.setStroke(new BasicStroke(2));
+			g.drawOval(p.x - StreetsideLayer.IMG_MARKER_RADIUS, p.y - StreetsideLayer.IMG_MARKER_RADIUS, 2 * StreetsideLayer.IMG_MARKER_RADIUS, 2 * StreetsideLayer.IMG_MARKER_RADIUS);
+		}
+
+		// TODO: reimplement detections for Bing Metadata? RRH
+		if (img instanceof StreetsideImage && !((StreetsideImage) img).getDetections().isEmpty()) {
+			final Path2D trafficSign = new Path2D.Double();
+			trafficSign.moveTo(p.getX() - StreetsideLayer.TRAFFIC_SIGN_SIZE / 2d, p.getY() - StreetsideLayer.TRAFFIC_SIGN_HEIGHT_3RD);
+			trafficSign.lineTo(p.getX() + StreetsideLayer.TRAFFIC_SIGN_SIZE / 2d, p.getY() - StreetsideLayer.TRAFFIC_SIGN_HEIGHT_3RD);
+			trafficSign.lineTo(p.getX(), p.getY() + 2 * StreetsideLayer.TRAFFIC_SIGN_HEIGHT_3RD);
+			trafficSign.closePath();
+			g.setColor(Color.WHITE);
+			g.fill(trafficSign);
+			g.setStroke(new BasicStroke(1));
+			g.setColor(Color.RED);
+			g.draw(trafficSign);
+		}
+	}*/
+
+	@Override
+	public Icon getIcon() {
+		return StreetsidePlugin.LOGO.setSize(ImageSizes.LAYER).get();
+	}
+
+	@Override
+	public boolean isMergable(Layer other) {
+		return false;
+	}
+
+	@Override
+	public void mergeFrom(Layer from) {
+		throw new UnsupportedOperationException(
+				"This layer does not support merging yet");
+	}
+
+	@Override
+	public Action[] getMenuEntries() {
+		return new Action[]{
+				LayerListDialog.getInstance().createShowHideLayerAction(),
+				LayerListDialog.getInstance().createDeleteLayerAction(),
+				new LayerListPopup.InfoAction(this)
+		};
+	}
+
+	@Override
+	public Object getInfoComponent() {
+		final IntSummaryStatistics seqSizeStats = getData().getSequences().stream().mapToInt(seq -> seq.getImages().size()).summaryStatistics();
+		return new StringBuilder(I18n.tr("Streetside layer"))
+				.append("\n")
+				.append(I18n.tr(
+						"{0} sequences, each containing between {1} and {2} images (ø {3})",
+						getData().getSequences().size(),
+						seqSizeStats.getCount() <= 0 ? 0 : seqSizeStats.getMin(),
+								seqSizeStats.getCount() <= 0 ? 0 : seqSizeStats.getMax(),
+										seqSizeStats.getAverage()
+						))
+				.append("\n\n")
+				.append(I18n.tr(
+						"{0} imported images",
+						getData().getImages().stream().filter(i -> i instanceof StreetsideImportedImage).count()
+						))
+				.append("\n+ ")
+				.append(I18n.tr(
+						"{0} downloaded images",
+						getData().getImages().stream().filter(i -> i instanceof StreetsideImage).count()
+						))
+				.append("\n= ")
+				.append(I18n.tr(
+						"{0} images in total",
+						getData().getImages().size()
+						)).toString();
+	}
+
+	@Override
+	public String getToolTipText() {
+		return I18n.tr("{0} images in {1} sequences", getData().getImages().size(), getData().getSequences().size());
+	}
+
+	@Override
+	public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
+		if (MainApplication.getLayerManager().getActiveLayer() == this) {
+			StreetsideUtils.updateHelpText();
+		}
+
+		if (MainApplication.getLayerManager().getEditLayer() != e.getPreviousDataLayer()) {
+			if (MainApplication.getLayerManager().getEditLayer() != null) {
+				MainApplication.getLayerManager().getEditLayer().getDataSet().addDataSetListener(StreetsideLayer.DATASET_LISTENER);
+			}
+			if (e.getPreviousDataLayer() != null) {
+				e.getPreviousDataLayer().getDataSet().removeDataSetListener(StreetsideLayer.DATASET_LISTENER);
+			}
+		}
+	}
+
+	@Override
+	public void visitBoundingBox(BoundingXYVisitor v) {
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.streetside.StreetsideDataListener#imagesAdded()
+	 */
+	@Override
+	public void imagesAdded() {
+		// TODO: Never used - could this be of use? @rrh
+		updateNearestImages();
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.mapillary.StreetsideDataListener#selectedImageChanged(org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage, org.openstreetmap.josm.plugins.mapillary.MapillaryAbstractImage)
+	 */
+	@Override
+	public void selectedImageChanged(StreetsideAbstractImage oldImage, StreetsideAbstractImage newImage) {
+		updateNearestImages();
+	}
+
+	/**
+	 * Returns the closest images belonging to a different sequence and
+	 * different from the specified target image.
+	 *
+	 * @param target the image for which you want to find the nearest other images
+	 * @param limit the maximum length of the returned array
+	 * @return An array containing the closest images belonging to different sequences sorted by distance from target.
+	 */
+	private StreetsideImage[] getNearestImagesFromDifferentSequences(StreetsideAbstractImage target, int limit) {
+		return data.getSequences().parallelStream()
+				.filter(seq -> seq.getId() != null && !seq.getId().equals(target.getSequence().getId()))
+				.map(seq -> { // Maps sequence to image from sequence that is nearest to target
+					final Optional<StreetsideAbstractImage> resImg = seq.getImages().parallelStream()
+							.filter(img -> img instanceof StreetsideImage && img.isVisible())
+							.min(new NearestImgToTargetComparator(target));
+					return resImg.orElse(null);
+				})
+				.filter(img -> // Filters out images too far away from target
+				img != null &&
+				img.getMovingLatLon().greatCircleDistance(target.getMovingLatLon())
+				< StreetsideProperties.SEQUENCE_MAX_JUMP_DISTANCE.get()
+						)
+				.sorted(new NearestImgToTargetComparator(target))
+				.limit(limit)
+				.toArray(StreetsideImage[]::new);
+	}
+
+	/**
+	 * Returns the closest images belonging to a different sequence and
+	 * different from the specified target image.
+	 *
+	 * @param target the image for which you want to find the nearest other images
+	 * @param limit the maximum length of the returned array
+	 * @return An array containing the closest images belonging to different sequences sorted by distance from target.
+	 */
+	/*private StreetsideCubemap[] getNearestCubemapsFromDifferentSequences(StreetsideAbstractImage target, int limit) {
+		return data.getSequences().parallelStream()
+				.filter(seq -> seq.getId() != null && !seq.getId().equals(target.getSequence().getId()))
+				.map(seq -> { // Maps sequence to image from sequence that is nearest to target
+					final Optional<StreetsideAbstractImage> resCb = seq.getImages().parallelStream()
+							.filter(cb -> cb instanceof StreetsideCubemap && cb.isVisible())
+							.min(new NearestCbToTargetComparator(target));
+					return resCb.orElse(null);
+				})
+				.filter(cb -> // Filters out images too far away from target
+				cb != null &&
+				cb.getMovingLatLon().greatCircleDistance(target.getMovingLatLon())
+				< StreetsideProperties.SEQUENCE_MAX_JUMP_DISTANCE.get()
+						)
+				.sorted(new NearestCbToTargetComparator(target))
+				.limit(limit)
+				.toArray(StreetsideCubemap[]::new);
+	}*/
+
+	private synchronized void updateNearestImages() {
+		final StreetsideAbstractImage selected = data.getSelectedImage();
+		if (selected != null) {
+			// TODO: could this be used to pre-cache cubemaps? @rrh
+			nearestImages = getNearestImagesFromDifferentSequences(selected, 2);
+		} else {
+			nearestImages = new StreetsideImage[0];
+		}
+		if (MainApplication.isDisplayingMapView()) {
+			StreetsideMainDialog.getInstance().redButton.setEnabled(nearestImages.length >= 1);
+			StreetsideMainDialog.getInstance().blueButton.setEnabled(nearestImages.length >= 2);
+		}
+		if (nearestImages.length >= 1) {
+			CacheUtils.downloadPicture(nearestImages[0]);
+			// TODO: download/pre-caches cubemaps here?
+			//CacheUtils.downloadCubemap(nearestImages[0]);
+			if (nearestImages.length >= 2) {
+				CacheUtils.downloadPicture(nearestImages[1]);
+				// TODO: download/pre-caches cubemaps here?
+				//CacheUtils.downloadCubemap(nearestImages[1]);
+			}
+		}
+	}
+
+	private static class NearestImgToTargetComparator implements Comparator<StreetsideAbstractImage> {
+		private final StreetsideAbstractImage target;
+
+		public NearestImgToTargetComparator(StreetsideAbstractImage target) {
+			this.target = target;
+		}
+		/* (non-Javadoc)
+		 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+		 */
+		@Override
+		public int compare(StreetsideAbstractImage img1, StreetsideAbstractImage img2) {
+			return (int) Math.signum(
+					img1.getMovingLatLon().greatCircleDistance(target.getMovingLatLon()) -
+					img2.getMovingLatLon().greatCircleDistance(target.getMovingLatLon())
+					);
+		}
+	}
+
+	private static class NearestCbToTargetComparator implements Comparator<StreetsideAbstractImage> {
+		private final StreetsideAbstractImage target;
+
+		public NearestCbToTargetComparator(StreetsideAbstractImage target) {
+			this.target = target;
+		}
+		/* (non-Javadoc)
+		 * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+		 */
+		@Override
+		public int compare(StreetsideAbstractImage img1, StreetsideAbstractImage img2) {
+			return (int) Math.signum(
+					img1.getMovingLatLon().greatCircleDistance(target.getMovingLatLon()) -
+					img2.getMovingLatLon().greatCircleDistance(target.getMovingLatLon())
+					);
+		}
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideLocationChangeset.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideLocationChangeset.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideLocationChangeset.java	(revision 34317)
@@ -0,0 +1,53 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside;
+
+import java.util.AbstractSet;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideChangesetListener;
+
+public class StreetsideLocationChangeset extends AbstractSet<StreetsideImage> {
+  private final Set<StreetsideChangesetListener> listeners = new HashSet<>();
+  private final Set<StreetsideImage> changeset = Collections.newSetFromMap(new ConcurrentHashMap<>());
+
+  public void addChangesetListener(StreetsideChangesetListener listener) {
+    listeners.add(listener);
+  }
+
+  public void cleanChangeset() {
+    changeset.clear();
+    fireListeners();
+  }
+
+  private void fireListeners() {
+    listeners.forEach(StreetsideChangesetListener::changesetChanged);
+  }
+
+  @Override
+  public boolean add(StreetsideImage image) {
+    boolean add = changeset.add(image);
+    fireListeners();
+    return add;
+  }
+
+  @Override
+  public Iterator<StreetsideImage> iterator() {
+    return changeset.iterator();
+  }
+
+  @Override
+  public int size() {
+    return changeset.size();
+  }
+
+  @Override
+  public boolean remove(Object image) {
+    boolean remove = changeset.remove(image);
+    fireListeners();
+    return remove;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsidePlugin.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsidePlugin.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsidePlugin.java	(revision 34317)
@@ -0,0 +1,138 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside;
+
+import java.io.IOException;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.MainMenu;
+import org.openstreetmap.josm.gui.MapFrame;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
+import org.openstreetmap.josm.plugins.Plugin;
+import org.openstreetmap.josm.plugins.PluginInformation;
+import org.openstreetmap.josm.plugins.streetside.actions.StreetsideDownloadAction;
+import org.openstreetmap.josm.plugins.streetside.actions.StreetsideDownloadViewAction;
+import org.openstreetmap.josm.plugins.streetside.actions.StreetsideExportAction;
+import org.openstreetmap.josm.plugins.streetside.actions.StreetsideJoinAction;
+import org.openstreetmap.josm.plugins.streetside.actions.StreetsideWalkAction;
+import org.openstreetmap.josm.plugins.streetside.actions.StreetsideZoomAction;
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapBuilder;
+import org.openstreetmap.josm.plugins.streetside.gui.StreetsideMainDialog;
+import org.openstreetmap.josm.plugins.streetside.gui.StreetsidePreferenceSetting;
+import org.openstreetmap.josm.plugins.streetside.gui.StreetsideViewerDialog;
+import org.openstreetmap.josm.plugins.streetside.gui.imageinfo.ImageInfoHelpPopup;
+import org.openstreetmap.josm.plugins.streetside.gui.imageinfo.ImageInfoPanel;
+import org.openstreetmap.josm.plugins.streetside.oauth.StreetsideUser;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+/**
+ * This is the main class of the Streetside plugin.
+ */
+public class StreetsidePlugin extends Plugin {
+
+  public static final ImageProvider LOGO = new ImageProvider("streetside-logo");
+
+  /** Zoom action */
+  private static final StreetsideZoomAction ZOOM_ACTION = new StreetsideZoomAction();
+  /** Walk action */
+  private static final StreetsideWalkAction WALK_ACTION = new StreetsideWalkAction();
+  /** Upload action */
+  //private static final StreetsideUploadAction UPLOAD_ACTION = new StreetsideUploadAction();
+
+  static {
+    if (Main.main != null) {
+      MainMenu.add(MainApplication.getMenu().fileMenu, new StreetsideExportAction(), false, 14);
+      MainMenu.add(MainApplication.getMenu().imagerySubMenu, new StreetsideDownloadAction(), false);
+      MainMenu.add(MainApplication.getMenu().viewMenu, ZOOM_ACTION, false, 15);
+      MainMenu.add(MainApplication.getMenu().fileMenu, new StreetsideDownloadViewAction(), false, 14);
+      MainMenu.add(MainApplication.getMenu().dataMenu, new StreetsideJoinAction(), false);
+      MainMenu.add(MainApplication.getMenu().moreToolsMenu, WALK_ACTION, false);
+      //MainMenu.add(MainApplication.getMenu().imagerySubMenu, new MapObjectLayerAction(), false);
+    }
+  }
+
+  /**
+   * Main constructor.
+   *
+   * @param info
+   *          Required information of the plugin. Obtained from the jar file.
+   * @throws IOException if the streetside cache directory is not found
+   */
+  public StreetsidePlugin(PluginInformation info) /*throws IOException*/ {
+    super(info);
+
+    if (StreetsideProperties.ACCESS_TOKEN.get() == null) {
+      StreetsideUser.setTokenValid(false);
+    }
+  }
+
+  static StreetsideDataListener[] getStreetsideDataListeners() {
+	return new StreetsideDataListener[]{/*UPLOAD_ACTION,*/ WALK_ACTION, ZOOM_ACTION, CubemapBuilder.getInstance()};
+  }
+
+
+  /**
+   * @return the {@link StreetsideWalkAction} for the plugin
+   */
+  public static StreetsideWalkAction getStreetsideWalkAction() {
+    return WALK_ACTION;
+  }
+
+  /**
+   * Called when the JOSM map frame is created or destroyed.
+   */
+  @Override
+  public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
+    if (oldFrame == null && newFrame != null) { // map frame added
+      MainApplication.getMap().addToggleDialog(StreetsideMainDialog.getInstance(), false);
+      StreetsideMainDialog.getInstance().setImageInfoHelp(new ImageInfoHelpPopup(
+    	  MainApplication.getMap().addToggleDialog(ImageInfoPanel.getInstance(), false)
+      ));
+      MainApplication.getMap().addToggleDialog(StreetsideViewerDialog.getInstance(), false);
+      //MainApplication.getMap().addToggleDialog(StreetsideHistoryDialog.getInstance(), false);
+      //MainApplication.getMap().addToggleDialog(StreetsideChangesetDialog.getInstance(), false);
+      //MainApplication.getMap().addToggleDialog(StreetsideFilterDialog.getInstance(), false);
+    }
+    if (oldFrame != null && newFrame == null) { // map frame destroyed
+      StreetsideMainDialog.destroyInstance();
+      //StreetsideHistoryDialog.destroyInstance();
+      //StreetsideChangesetDialog.destroyInstance();
+      //StreetsideFilterDialog.destroyInstance();
+      ImageInfoPanel.destroyInstance();
+      CubemapBuilder.destroyInstance();
+
+    }
+  }
+
+  @Override
+  public PreferenceSetting getPreferenceSetting() {
+    return new StreetsidePreferenceSetting();
+  }
+
+  /**
+   * @return the current {@link MapView} without throwing a {@link NullPointerException}
+   */
+  public static MapView getMapView() {
+    final MapFrame mf = MainApplication.getMap();
+    if (mf != null) {
+      return mf.mapView;
+    }
+    return null;
+  }
+
+  /**
+   * @return the {@link StreetsideUploadAction} for the plugin
+   */
+  /*public static StreetsideUploadAction getUploadAction() {
+    return UPLOAD_ACTION;
+  }*/
+
+  /**
+   * @return the {@link StreetsideZoomAction} for the plugin
+   */
+  /*public static StreetsideZoomAction getZoomAction() {
+    return ZOOM_ACTION;
+  }*/
+  }
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideSequence.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideSequence.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/StreetsideSequence.java	(revision 34317)
@@ -0,0 +1,234 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.openstreetmap.josm.plugins.streetside.model.UserProfile;
+
+/**
+ * Class that stores a sequence of {@link StreetsideAbstractImage} objects.
+ *
+ * @author nokutu
+ * @see StreetsideAbstractImage
+ */
+
+public class StreetsideSequence {
+
+
+  /**
+   * Unique identifier. Used only for {@link StreetsideImage} sequences.
+   */
+  private String id;
+  private UserProfile user;
+
+  private double la;
+  private double lo;
+
+  /**
+   * Epoch time when the sequence was created
+   */
+  private long cd;
+
+  /**
+   * The images in the sequence.
+   */
+  private List<StreetsideAbstractImage> images;
+
+  /**
+   * Unique identifier. Used only for {@link StreetsideImage} sequences.
+   */
+
+  /**
+   * @param string
+   * @param string2
+   * @param capturedAt2
+   */
+  public StreetsideSequence(String id, Long ca) {
+	this.id = id;
+    cd = ca;
+    images = new CopyOnWriteArrayList<>();
+  }
+
+  /**
+   * @param string
+   * @param la
+   * @param lo
+   */
+  public StreetsideSequence(String id, double la, double lo) {
+    this.id = id;
+    this.la = la;
+    this.lo = lo;
+    images = new CopyOnWriteArrayList<>();
+  }
+
+  /**
+   * 	No argument constructor for StreetsideSequence - necessary for JSON serialization
+   */
+  public StreetsideSequence() {
+	  images = new CopyOnWriteArrayList<>();
+  }
+
+  public StreetsideSequence(String id, double la, double lo, long ca) {
+	this.id = id;
+	this.la = la;
+	this.lo = lo;
+	cd = ca;
+	images = new CopyOnWriteArrayList<>();
+}
+
+// TODO: Are all my sequences only set with id values? (no LatLon/Cas?) @rrh
+public StreetsideSequence(String id) {
+	this.id = id;
+	images = new CopyOnWriteArrayList<>();
+}
+
+/**
+   * Adds a new {@link StreetsideAbstractImage} object to the database.
+   *
+   * @param image The {@link StreetsideAbstractImage} object to be added
+   */
+  public synchronized void add(StreetsideAbstractImage image) {
+    images.add(image);
+    image.setSequence(this);
+  }
+
+  /**
+   * Adds a set of {@link StreetsideAbstractImage} objects to the database.
+   *
+   * @param images The set of {@link StreetsideAbstractImage} objects to be added.
+   */
+  public synchronized void add(Collection<? extends StreetsideAbstractImage> images) {
+    this.images.addAll(images);
+    images.forEach(img -> img.setSequence(this));
+  }
+
+  /**
+   * Returns the next {@link StreetsideAbstractImage} in the sequence of a given
+   * {@link StreetsideAbstractImage} object.
+   *
+   * @param image The {@link StreetsideAbstractImage} object whose next image is
+   * going to be returned.
+   *
+   * @return The next {@link StreetsideAbstractImage} object in the sequence.
+   *
+   * @throws IllegalArgumentException if the given {@link StreetsideAbstractImage} object doesn't belong
+   * the this sequence.
+   */
+  public StreetsideAbstractImage next(StreetsideAbstractImage image) {
+    int i = images.indexOf(image);
+    if (i == -1) {
+      throw new IllegalArgumentException();
+    }
+    if (i == images.size() - 1) {
+      return null;
+    }
+    return images.get(i + 1);
+  }
+
+  /**
+   * Returns the previous {@link StreetsideAbstractImage} in the sequence of a
+   * given {@link StreetsideAbstractImage} object.
+   *
+   * @param image The {@link StreetsideAbstractImage} object whose previous image is
+   * going to be returned.
+   *
+   * @return The previous {@link StreetsideAbstractImage} object in the sequence.
+   *
+   * @throws IllegalArgumentException if the given {@link StreetsideAbstractImage} object doesn't belong
+   * the this sequence.
+   */
+  public StreetsideAbstractImage previous(StreetsideAbstractImage image) {
+    int i = images.indexOf(image);
+    if (i < 0) {
+      throw new IllegalArgumentException();
+    }
+    if (i == 0) {
+      return null;
+    }
+    return images.get(i - 1);
+  }
+
+  /**
+   * Removes a {@link StreetsideAbstractImage} object from the database.
+   *
+   * @param image The {@link StreetsideAbstractImage} object to be removed.
+   */
+  public void remove(StreetsideAbstractImage image) {
+    images.remove(image);
+  }
+
+  /**
+   * @param id the id to set
+   */
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  /**
+   * @return the la
+   */
+  public double getLa() {
+    return la;
+  }
+
+  /**
+   * @param la the la to set
+   */
+  public void setLa(double la) {
+    this.la = la;
+  }
+
+  /**
+   * @return the lo
+   */
+  public double getLo() {
+    return lo;
+  }
+
+  /**
+   * @param lo the lo to set
+   */
+  public void setLo(double lo) {
+    this.lo = lo;
+  }
+
+  /**
+   * Returns the Epoch time when the sequence was captured.
+   *
+   * Negative values mean, no value is set.
+   *
+   * @return A long containing the Epoch time when the sequence was captured.
+   */
+  public long getCd() {
+    return cd;
+  }
+
+  /**
+   * Returns all {@link StreetsideAbstractImage} objects contained by this
+   * object.
+   *
+   * @return A {@link List} object containing all the
+   * {@link StreetsideAbstractImage} objects that are part of the
+   * sequence.
+   */
+  public List<StreetsideAbstractImage> getImages() {
+    return images;
+  }
+
+  /**
+   * Returns the unique identifier of the sequence.
+   *
+   * @return A {@code String} containing the unique identifier of the sequence.
+   * null means that the sequence has been created locally for imported
+   * images.
+   */
+  public String getId() {
+    return id;
+  }
+
+  public UserProfile getUser() {
+	return user;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/ImageReloadAction.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/ImageReloadAction.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/ImageReloadAction.java	(revision 34317)
@@ -0,0 +1,28 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.actions;
+
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapBuilder;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
+
+import org.openstreetmap.josm.plugins.streetside.gui.StreetsideMainDialog;
+
+public class ImageReloadAction extends AbstractAction {
+
+	private static final long serialVersionUID = 7987479726049238315L;
+
+	public ImageReloadAction(final String name) {
+		 super(name, ImageProvider.get("reload", ImageSizes.SMALLICON));
+	}
+
+	@Override
+	public void actionPerformed(ActionEvent arg0) {
+		if(StreetsideMainDialog.getInstance().getImage()!=null){
+			CubemapBuilder.getInstance().reload(CubemapBuilder.getInstance().getCubemap().getId());
+		}
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideDownloadAction.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideDownloadAction.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideDownloadAction.java	(revision 34317)
@@ -0,0 +1,71 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.plugins.streetside.StreetsidePlugin;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
+import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.Shortcut;
+
+/**
+ * Action that triggers the plugin. If in automatic mode, it will automatically
+ * download the images in the areas where there is OSM data.
+ *
+ * @author nokutu
+ *
+ */
+public class StreetsideDownloadAction extends JosmAction {
+
+  private static final long serialVersionUID = 4426446157849005029L;
+  public static final Shortcut SHORTCUT = Shortcut.registerShortcut("Streetside", tr("Open Streetside layer"), KeyEvent.VK_COMMA, Shortcut.SHIFT);
+
+  /**
+   * Main constructor.
+   */
+  public StreetsideDownloadAction() {
+    super(
+        tr("Streetside"),
+        new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT),
+        tr("Open Streetside layer"),
+        SHORTCUT,
+        false,
+        "streetsideDownload",
+        false
+    );
+  }
+
+  @Override
+  public void actionPerformed(ActionEvent ae) {
+    if (!StreetsideLayer.hasInstance()) {
+      // A new streetside layer is created, so the active layer is not changed
+      StreetsideLayer.getInstance();
+      return;
+    } else if (!MainApplication.getLayerManager().containsLayer(StreetsideLayer.getInstance())) {
+      MainApplication.getLayerManager().addLayer(StreetsideLayer.getInstance());
+      return;
+    }
+
+    try {
+      // Successive calls to this action toggle the active layer between the OSM data layer and the streetside layer
+      OsmDataLayer editLayer = MainApplication.getLayerManager().getEditLayer();
+      if (MainApplication.getLayerManager().getActiveLayer() != StreetsideLayer.getInstance()) {
+        MainApplication.getLayerManager().setActiveLayer(StreetsideLayer.getInstance());
+      } else if (editLayer != null) {
+        MainApplication.getLayerManager().setActiveLayer(editLayer);
+      }
+    } catch (IllegalArgumentException e) {
+      // If the StreetsideLayer is not managed by LayerManager but you try to set it as active layer
+      Logging.warn(e);
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideDownloadViewAction.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideDownloadViewAction.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideDownloadViewAction.java	(revision 34317)
@@ -0,0 +1,76 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.actions;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.data.preferences.AbstractProperty.ValueChangeEvent;
+import org.openstreetmap.josm.data.preferences.AbstractProperty.ValueChangeListener;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.StreetsidePlugin;
+import org.openstreetmap.josm.plugins.streetside.io.download.StreetsideDownloader;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
+import org.openstreetmap.josm.tools.Shortcut;
+
+/**
+ * If in "download images in visible area" mode, downloads all the images in the current view.
+ *
+ * @author nokutu
+ *
+ */
+public class StreetsideDownloadViewAction extends JosmAction implements ValueChangeListener<String> {
+
+  private static final long serialVersionUID = 6738276777802831669L;
+
+  private static final String DESCRIPTION = I18n.marktr("Download Streetside images in current view");
+
+  /**
+   * Main constructor.
+   */
+  public StreetsideDownloadViewAction() {
+    super(
+      I18n.tr(DESCRIPTION),
+      new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT),
+      I18n.tr(DESCRIPTION),
+      Shortcut.registerShortcut("Streetside area", I18n.tr(DESCRIPTION), KeyEvent.VK_PERIOD, Shortcut.SHIFT),
+      false,
+      "streetsideArea",
+      true
+    );
+    StreetsideProperties.DOWNLOAD_MODE.addListener(this);
+    initEnabledState();
+  }
+
+  @Override
+  public void actionPerformed(ActionEvent arg0) {
+    StreetsideDownloader.downloadVisibleArea();
+  }
+
+  @Override
+  protected boolean listenToSelectionChange() {
+    return false;
+  }
+
+  /**
+   * Enabled when the Streetside layer is instantiated and download mode is either "osm area" or "manual".
+   */
+  @Override
+  protected void updateEnabledState() {
+    super.updateEnabledState();
+    setEnabled(
+      StreetsideLayer.hasInstance() && (
+        StreetsideDownloader.getMode() == StreetsideDownloader.DOWNLOAD_MODE.OSM_AREA
+        || StreetsideDownloader.getMode() == StreetsideDownloader.DOWNLOAD_MODE.MANUAL_ONLY
+      )
+    );
+  }
+
+  @Override
+  public void valueChanged(ValueChangeEvent<? extends String> e) {
+    updateEnabledState();
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideExportAction.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideExportAction.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideExportAction.java	(revision 34317)
@@ -0,0 +1,131 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImportedImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.StreetsidePlugin;
+import org.openstreetmap.josm.plugins.streetside.gui.StreetsideExportDialog;
+import org.openstreetmap.josm.plugins.streetside.io.export.StreetsideExportManager;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
+import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.Shortcut;
+
+/**
+ * Action that launches a StreetsideExportDialog and lets you export the images.
+ *
+ * @author nokutu
+ *
+ */
+public class StreetsideExportAction extends JosmAction {
+
+  private static final long serialVersionUID = 6131359489725632369L;
+
+  private StreetsideExportDialog dialog;
+
+  /**
+   * Main constructor.
+   */
+  public StreetsideExportAction() {
+    super(tr("Export Streetside images"), new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT),
+        tr("Export Streetside images"), Shortcut.registerShortcut("Export Streetside",
+            tr("Export Streetside images"), KeyEvent.CHAR_UNDEFINED,
+            Shortcut.NONE), false, "streetsideExport", true);
+    setEnabled(false);
+  }
+
+  @Override
+  public void actionPerformed(ActionEvent ae) {
+    JOptionPane pane = new JOptionPane();
+
+    JButton ok = new JButton("Ok");
+    ok.addActionListener(e -> pane.setValue(JOptionPane.OK_OPTION));
+    JButton cancel = new JButton(tr("Cancel"));
+    cancel.addActionListener(e -> pane.setValue(JOptionPane.CANCEL_OPTION));
+
+    dialog = new StreetsideExportDialog(ok);
+    pane.setMessage(dialog);
+    pane.setOptions(new JButton[] {ok, cancel});
+
+    JDialog dlg = pane.createDialog(Main.parent, tr("Export Streetside images"));
+    dlg.setMinimumSize(new Dimension(400, 150));
+    dlg.setVisible(true);
+
+    // Checks if the inputs are correct and starts the export process.
+    if (pane.getValue() != null
+        && (int) pane.getValue() == JOptionPane.OK_OPTION
+        && dialog.chooser != null) {
+      if (dialog.group.isSelected(dialog.all.getModel())) {
+        export(StreetsideLayer.getInstance().getData().getImages());
+      } else if (dialog.group.isSelected(dialog.sequence.getModel())) {
+        Set<StreetsideAbstractImage> images = new ConcurrentSkipListSet<>();
+        for (StreetsideAbstractImage image : StreetsideLayer.getInstance().getData().getMultiSelectedImages()) {
+          if (image instanceof StreetsideImage) {
+            if (!images.contains(image)) {
+              images.addAll(image.getSequence().getImages());
+            }
+          } else {
+            images.add(image);
+          }
+        }
+        export(images);
+      } else if (dialog.group.isSelected(dialog.selected.getModel())) {
+        export(StreetsideLayer.getInstance().getData().getMultiSelectedImages());
+      }
+      // This option ignores the selected directory.
+    } else if (dialog.group.isSelected(dialog.rewrite.getModel())) {
+      ArrayList<StreetsideImportedImage> images = new ArrayList<>();
+      StreetsideLayer.getInstance().getData().getImages().stream().filter(img -> img instanceof StreetsideImportedImage).forEach(img -> images.add((StreetsideImportedImage) img));
+      try {
+        MainApplication.worker.execute(new StreetsideExportManager(images));
+      } catch (IOException e1) {
+        Logging.error(e1);
+      }
+    }
+    dlg.dispose();
+  }
+
+  /**
+   * Exports the given images from the database.
+   *
+   * @param images
+   *          The set of images to be exported.
+   */
+  public void export(Set<StreetsideAbstractImage> images) {
+    MainApplication.worker.execute(new StreetsideExportManager(images,
+        dialog.chooser.getSelectedFile().toString()));
+  }
+
+  @Override
+  protected boolean listenToSelectionChange() {
+    return false;
+  }
+
+  /**
+   * Enabled when streetside layer is in layer list
+   */
+  @Override
+  protected void updateEnabledState() {
+    super.updateEnabledState();
+    setEnabled(StreetsideLayer.hasInstance());
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideJoinAction.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideJoinAction.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideJoinAction.java	(revision 34317)
@@ -0,0 +1,56 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.mode.JoinMode;
+import org.openstreetmap.josm.plugins.streetside.mode.SelectMode;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
+
+/**
+ * Changes the mode of the Layer, from Select mode to Join mode and vice versa.
+ *
+ * @author nokutu
+ *
+ */
+public class StreetsideJoinAction extends JosmAction {
+
+  private static final long serialVersionUID = -7082300908202843706L;
+
+  /**
+   * Main constructor.
+   */
+  public StreetsideJoinAction() {
+    super(tr("Join mode"), new ImageProvider("mapmode", "mapillary-join").setSize(ImageSizes.DEFAULT),
+        tr("Join/unjoin pictures"), null, false, "mapillaryJoin", true);
+  }
+
+  @Override
+  public void actionPerformed(ActionEvent arg0) {
+    if (StreetsideLayer.getInstance().mode instanceof SelectMode) {
+      StreetsideLayer.getInstance().setMode(new JoinMode());
+    } else {
+      StreetsideLayer.getInstance().setMode(new SelectMode());
+    }
+  }
+
+  @Override
+  protected boolean listenToSelectionChange() {
+    return false;
+  }
+
+  /**
+   * Enabled when mapillary layer is the active layer
+   */
+  @Override
+  protected void updateEnabledState() {
+    super.updateEnabledState();
+    setEnabled(MainApplication.getLayerManager().getActiveLayer() instanceof StreetsideLayer);
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideWalkAction.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideWalkAction.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideWalkAction.java	(revision 34317)
@@ -0,0 +1,123 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JDialog;
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideDataListener;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.StreetsidePlugin;
+import org.openstreetmap.josm.plugins.streetside.gui.StreetsideMainDialog;
+import org.openstreetmap.josm.plugins.streetside.gui.StreetsideWalkDialog;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
+
+/**
+ * Walks forward at a given interval.
+ *
+ * @author nokutu
+ *
+ */
+public class StreetsideWalkAction extends JosmAction implements StreetsideDataListener {
+
+  private static final long serialVersionUID = 3454223919402245818L;
+
+  private WalkThread thread;
+  private final List<WalkListener> listeners = new ArrayList<>();
+
+  /**
+   *
+   */
+  public StreetsideWalkAction() {
+    super(tr("Walk mode"), new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT),
+        tr("Walk mode"), null,
+        false, "streetsideWalk", true);
+  }
+
+  @Override
+  public void actionPerformed(ActionEvent arg0) {
+    StreetsideWalkDialog dialog = new StreetsideWalkDialog();
+    JOptionPane pane = new JOptionPane(dialog, JOptionPane.PLAIN_MESSAGE,
+        JOptionPane.OK_CANCEL_OPTION);
+    JDialog dlg = pane.createDialog(Main.parent, tr("Walk mode"));
+    dlg.setMinimumSize(new Dimension(400, 150));
+    dlg.setVisible(true);
+    if (pane.getValue() != null
+        && (int) pane.getValue() == JOptionPane.OK_OPTION) {
+      thread = new WalkThread((int) dialog.spin.getValue(),
+          dialog.waitForPicture.isSelected(),
+          dialog.followSelection.isSelected(), dialog.goForward.isSelected());
+      fireWalkStarted();
+      thread.start();
+      StreetsideMainDialog.getInstance().setMode(StreetsideMainDialog.MODE.WALK);
+    }
+  }
+
+  @Override
+  public void imagesAdded() {
+    // Nothing
+  }
+
+  /**
+   * Adds a listener.
+   *
+   * @param lis
+   *          The listener to be added.
+   */
+  public void addListener(WalkListener lis) {
+    listeners.add(lis);
+  }
+
+  /**
+   * Removes a listener.
+   *
+   * @param lis
+   *          The listener to be added.
+   */
+  public void removeListener(WalkListener lis) {
+    listeners.remove(lis);
+  }
+
+  private void fireWalkStarted() {
+    if (listeners.isEmpty()) {
+      return;
+    }
+    for (WalkListener lis : listeners) {
+      lis.walkStarted(thread);
+    }
+  }
+
+  @Override
+  protected boolean listenToSelectionChange() {
+    return false;
+  }
+
+  @Override
+  public void selectedImageChanged(StreetsideAbstractImage oldImage, StreetsideAbstractImage newImage) {
+    if (oldImage == null && newImage != null) {
+      setEnabled(true);
+    } else if (oldImage != null && newImage == null) {
+      setEnabled(false);
+    }
+  }
+
+  /**
+   * Enabled when a mapillary image is selected.
+   */
+  @Override
+  protected void updateEnabledState() {
+    super.updateEnabledState();
+    setEnabled(StreetsideLayer.hasInstance() && StreetsideLayer.getInstance().getData().getSelectedImage() != null);
+  }
+
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideZoomAction.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideZoomAction.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/StreetsideZoomAction.java	(revision 34317)
@@ -0,0 +1,76 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideDataListener;
+import org.openstreetmap.josm.plugins.streetside.StreetsidePlugin;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
+
+/**
+ * Zooms to the currently selected image.
+ *
+ * @author nokutu
+ *
+ */
+public class StreetsideZoomAction extends JosmAction implements StreetsideDataListener {
+
+  private static final long serialVersionUID = -5885977359895624233L;
+
+  /**
+   * Main constructor.
+   */
+  public StreetsideZoomAction() {
+    super(
+      tr("Zoom to selected image"),
+      new ImageProvider(StreetsidePlugin.LOGO).setSize(ImageSizes.DEFAULT),
+      tr("Zoom to the currently selected Streetside image"),
+      null,
+      false,
+      "mapillaryZoom",
+      true
+    );
+  }
+
+  @Override
+  public void actionPerformed(ActionEvent arg0) {
+    if (StreetsideLayer.getInstance().getData().getSelectedImage() == null) {
+      throw new IllegalStateException();
+    }
+    MainApplication.getMap().mapView.zoomTo(StreetsideLayer.getInstance().getData()
+        .getSelectedImage().getMovingLatLon());
+  }
+
+  @Override
+  public void imagesAdded() {
+    // Nothing
+  }
+
+    @Override
+  protected boolean listenToSelectionChange() {
+    return false;
+  }
+
+  @Override
+  public void selectedImageChanged(StreetsideAbstractImage oldImage, StreetsideAbstractImage newImage) {
+    if (oldImage == null && newImage != null) {
+      setEnabled(true);
+    } else if (oldImage != null && newImage == null) {
+      setEnabled(false);
+    }
+  }
+
+  @Override
+  protected void updateEnabledState() {
+    super.updateEnabledState();
+    setEnabled(StreetsideLayer.hasInstance() && StreetsideLayer.getInstance().getData().getSelectedImage() != null);
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/WalkListener.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/WalkListener.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/WalkListener.java	(revision 34317)
@@ -0,0 +1,19 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.actions;
+
+/**
+ * Implemented by those classes that need to listen to the creation of the walk
+ * threads.
+ *
+ * @author nokutu
+ *
+ */
+public interface WalkListener {
+
+  /**
+   * Called when a new walk thread is started.
+   *
+   * @param thread The thread executing the walk.
+   */
+  void walkStarted(WalkThread thread);
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/WalkThread.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/WalkThread.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/WalkThread.java	(revision 34317)
@@ -0,0 +1,243 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.actions;
+
+import java.awt.image.BufferedImage;
+
+import javax.swing.SwingUtilities;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideData;
+import org.openstreetmap.josm.plugins.streetside.StreetsideDataListener;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.cache.CacheUtils;
+import org.openstreetmap.josm.plugins.streetside.gui.StreetsideMainDialog;
+
+
+/**
+ * Thread containing the walk process.
+ *
+ * @author nokutu
+ */
+public class WalkThread extends Thread implements StreetsideDataListener {
+  private final int interval;
+  private final StreetsideData data;
+  private boolean end;
+  private final boolean waitForFullQuality;
+  private final boolean followSelected;
+  private final boolean goForward;
+  private BufferedImage lastImage;
+  private volatile boolean paused;
+
+  /**
+   * Main constructor.
+   *
+   * @param interval How often the images switch.
+   * @param waitForPicture If it must wait for the full resolution picture or just the
+   * thumbnail.
+   * @param followSelected Zoom to each image that is selected.
+   * @param goForward true to go forward; false to go backwards.
+   */
+  public WalkThread(int interval, boolean waitForPicture,
+                    boolean followSelected, boolean goForward) {
+    this.interval = interval;
+    waitForFullQuality = waitForPicture;
+    this.followSelected = followSelected;
+    this.goForward = goForward;
+    data = StreetsideLayer.getInstance().getData();
+    data.addListener(this);
+  }
+
+  @Override
+  public void run() {
+    try {
+      while (!end && data.getSelectedImage().next() != null) {
+        StreetsideAbstractImage image = data.getSelectedImage();
+        if (image != null && image.next() instanceof StreetsideImage) {
+          // Predownload next 10 thumbnails.
+          preDownloadImages((StreetsideImage) image.next(), 10, CacheUtils.PICTURE.THUMBNAIL);
+          // TODO: WalkThread for cubemaps? @rrh
+      	  //preDownloadCubemaps((StreetsideImage) image.next(), 10, CacheUtils.PICTURE.CUBEMAP);
+          if (waitForFullQuality) {
+            // Start downloading 3 next full images.
+            StreetsideAbstractImage currentImage = image.next();
+        	preDownloadImages((StreetsideImage) currentImage, 3, CacheUtils.PICTURE.FULL_IMAGE);
+        	// TODO: WalkThread for cubemaps? @rrh
+        	/*if (StreetsideProperties.PREDOWNLOAD_CUBEMAPS.get().booleanValue()) {
+          	  preDownloadCubemaps((StreetsideImage) currentImage, 3, CacheUtils.PICTURE.CUBEMAP);
+            }*/
+          }
+        }
+        try {
+          // Waits for full quality picture.
+          final BufferedImage displayImage = StreetsideMainDialog.getInstance().getStreetsideImageDisplay().getImage();
+          if (waitForFullQuality && image instanceof StreetsideImage) {
+            while (displayImage == lastImage || displayImage == null || displayImage.getWidth() < 2048) {
+              Thread.sleep(100);
+            }
+          } else { // Waits for thumbnail.
+            while (displayImage == lastImage || displayImage == null || displayImage.getWidth() < 320) {
+              Thread.sleep(100);
+            }
+          }
+          while (paused) {
+            Thread.sleep(100);
+          }
+          wait(interval);
+          while (paused) {
+            Thread.sleep(100);
+          }
+          lastImage = StreetsideMainDialog.getInstance().getStreetsideImageDisplay().getImage();
+          if (goForward) {
+            data.selectNext(followSelected);
+          } else {
+            data.selectPrevious(followSelected);
+          }
+        } catch (InterruptedException e) {
+          return;
+        }
+      }
+
+    	// TODO: WalkThread for cubemaps? @rrh
+      	/*while (!end && data.getSelectedImage().next() != null) {
+            StreetsideAbstractImage cubemap = data.getSelectedImage();
+            if (cubemap != null && cubemap.next() instanceof StreetsideCubemap) {
+              if (waitForFullQuality) {
+                // Start downloading 3 next full images.
+
+            	// TODO: cubemap handling @rrh
+            	preDownloadCubemaps((StreetsideCubemap) cubemap.next(), 6, CacheUtils.PICTURE.CUBEMAP);
+              }
+            }
+            try {
+              // Waits for full quality picture.
+              final BufferedImage[] displayCubemap = StreetsideMainDialog.getInstance().streetsideViewerDisplay.getCubemap();
+              if (waitForFullQuality && cubemap instanceof StreetsideCubemap) {
+                  // TODO: handle cubemap width? @rrh
+            	  while (displayCubemap == lastCubemap || displayCubemap == null || displayCubemap.getWidth() < 2048) {
+                  Thread.sleep(100);
+                }
+              } else { // Waits for thumbnail.
+            	  // TODO: handle cubemap width? @rrh
+            	  while (displayCubemap == lastCubemap || displayCubemap == null || displayCubemap.getWidth() < 320) {
+                  Thread.sleep(100);
+                }
+              }
+              while (paused) {
+                Thread.sleep(100);
+              }
+              wait(interval);
+              while (paused) {
+                Thread.sleep(100);
+              }
+              lastCubemap = StreetsideMainDialog.getInstance().streetsideViewerDisplay.getCubemap();
+              // TODO: forward / previous for cubemap? @rrh
+              if (goForward) {
+                data.selectNext(followSelected);
+              } else {
+                data.selectPrevious(followSelected);
+              }
+            } catch (InterruptedException e) {
+              return;
+            }
+          }*/
+    } catch (NullPointerException e) {
+      // TODO: Avoid NPEs instead of waiting until they are thrown and then catching them
+      return;
+    }
+    end();
+  }
+
+  private void preDownloadCubemaps(StreetsideImage startImage, int n, CacheUtils.PICTURE type) {
+	  if (n >= 1 && startImage != null) {
+
+		  for (int i = 0; i < 6; i++) {
+				for (int j = 0; j < 4; j++) {
+					for (int k = 0; k < 4; k++) {
+
+						CacheUtils.downloadPicture(startImage, type);
+						if (startImage.next() instanceof StreetsideImage && n >= 2) {
+							preDownloadImages((StreetsideImage) startImage.next(), n - 1, type);
+						}
+					}
+				}
+		  }
+	  }
+  }
+
+/**
+   * Downloads n images into the cache beginning from the supplied start-image (including the start-image itself).
+   *
+   * @param startImage the image to start with (this and the next n-1 images in the same sequence are downloaded)
+   * @param n the number of images to download
+   * @param type the quality of the image (full or thumbnail)
+   */
+  private static void preDownloadImages(StreetsideImage startImage, int n, CacheUtils.PICTURE type) {
+    if (n >= 1 && startImage != null) {
+      CacheUtils.downloadPicture(startImage, type);
+      if (startImage.next() instanceof StreetsideImage && n >= 2) {
+        preDownloadImages((StreetsideImage) startImage.next(), n - 1, type);
+      }
+    }
+  }
+
+  @Override
+  public void imagesAdded() {
+    // Nothing
+  }
+
+  @Override
+  public void selectedImageChanged(StreetsideAbstractImage oldImage, StreetsideAbstractImage newImage) {
+    if (newImage != oldImage.next()) {
+      end();
+      interrupt();
+    }
+  }
+
+  /**
+   * Continues with the execution if paused.
+   */
+  public void play() {
+    paused = false;
+  }
+
+  /**
+   * Pauses the execution.
+   */
+  public void pause() {
+    paused = true;
+  }
+
+  /**
+   * Stops the execution.
+   */
+  public void stopWalk() {
+    if (SwingUtilities.isEventDispatchThread()) {
+      end();
+      interrupt();
+    } else {
+      SwingUtilities.invokeLater(this::stopWalk);
+    }
+  }
+
+  /**
+   * Called when the walk stops by itself of forcefully.
+   */
+  public void end() {
+    if (SwingUtilities.isEventDispatchThread()) {
+      end = true;
+      data.removeListener(this);
+      StreetsideMainDialog.getInstance().setMode(StreetsideMainDialog.MODE.NORMAL);
+    } else {
+      SwingUtilities.invokeLater(this::end);
+    }
+    // TODO: WalkThread for Cubemaps? @rrh
+    /*if (Platform.isEventDispatchThread()) {
+        end = true;
+        data.removeListener(this);
+        StreetsideViewerDialog.getInstance().setMode(StreetsideViewerDialog.MODE.NORMAL);
+      } else {
+        Platform.invokeLater(this::end);
+      }*/
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/package-info.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/package-info.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/actions/package-info.java	(revision 34317)
@@ -0,0 +1,5 @@
+// License: GPL. For details, see LICENSE file.
+/**
+ * The main package in which all core-code (so at the moment all code) resides.
+ */
+package org.openstreetmap.josm.plugins.streetside.actions;
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/CacheUtils.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/CacheUtils.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/CacheUtils.java	(revision 34317)
@@ -0,0 +1,273 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.cache;
+
+
+import java.io.IOException;
+
+import org.openstreetmap.josm.data.cache.CacheEntry;
+import org.openstreetmap.josm.data.cache.CacheEntryAttributes;
+import org.openstreetmap.josm.data.cache.ICachedLoaderListener;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapBuilder;
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+* Utility methods for working with cache.
+*
+* @author nokutu
+*
+*/
+public final class CacheUtils {
+
+private static IgnoreDownload ignoreDownload = new IgnoreDownload();
+
+/** Picture quality */
+public enum PICTURE {
+ /** Thumbnail quality picture (320 p) */
+ THUMBNAIL,
+ /** Full quality picture (2048 p) */
+ FULL_IMAGE,
+ /** Both of them */
+ BOTH,
+ /** Streetside cubemap */
+ CUBEMAP
+}
+
+private CacheUtils() {
+ // Private constructor to avoid instantiation
+}
+
+/**
+* Downloads the the thumbnail and the full resolution picture of the given
+* image. Does nothing if it is already in cache.
+*
+* @param img
+*          The image whose picture is going to be downloaded.
+*/
+public static void downloadPicture(StreetsideImage img) {
+ downloadPicture(img, PICTURE.BOTH);
+}
+
+/**
+* Downloads the the thumbnail and the full resolution picture of the given
+* image. Does nothing if it is already in cache.
+*
+* @param img
+*          The image whose picture is going to be downloaded.
+*/
+public static void downloadCubemap(StreetsideImage cm) {
+	// TODO: causes errors. Analyze @rrh
+	//downloadPicture(cm, PICTURE.CUBEMAP);
+}
+
+/**
+* Downloads the picture of the given image. Does nothing when it is already
+* in cache.
+*
+* @param img
+*          The image to be downloaded.
+* @param pic
+*          The picture type to be downloaded (full quality, thumbnail or
+*          both.)
+*/
+public static void downloadPicture(StreetsideImage img, PICTURE pic) {
+ switch (pic) {
+   case BOTH:
+     if (new StreetsideCache(img.getId(), StreetsideCache.Type.THUMBNAIL).get() == null)
+       submit(img.getId(), StreetsideCache.Type.THUMBNAIL, ignoreDownload);
+     if (new StreetsideCache(img.getId(), StreetsideCache.Type.FULL_IMAGE).get() == null)
+       submit(img.getId(), StreetsideCache.Type.FULL_IMAGE, ignoreDownload);
+     break;
+   case THUMBNAIL:
+     submit(img.getId(), StreetsideCache.Type.THUMBNAIL, ignoreDownload);
+     break;
+   case FULL_IMAGE:
+   // TODO: is this still useful? @rrh
+   case CUBEMAP:
+	   if(img.getId()==null) {
+		   Logging.error("Download cancelled. Image id is null.");
+	   } else {
+		   CubemapBuilder.getInstance().downloadCubemapImages(img.getId());
+	   }
+	   break;
+   default:
+     submit(img.getId(), StreetsideCache.Type.FULL_IMAGE, ignoreDownload);
+     break;
+ }
+}
+
+/**
+* Downloads the picture of the given image. Does nothing when it is already
+* in cache.
+*
+* @param cm
+*          The cubemap to be downloaded.
+* @param pic
+*          The picture type to be downloaded (full quality, thumbnail, both, or cubemap.)
+*/
+/*public static void downloadCubemapFront(StreetsideImage cm, PICTURE pic) {
+ switch (pic) {
+   case CUBEMAP:
+	   for (int i = 0; i < 6; i++) {
+			for (int j = 0; j < 4; j++) {
+				for (int k = 0; k < 4; k++) {
+					String cubeface = CubemapUtils.getFaceNumberForCount(i);
+					String tileNr = CubemapUtils.rowCol2StreetsideCellAddressMap
+							.get(Integer.toString(j) + Integer.toString(k));
+					long tileId = Long.parseLong(cm.getId() + cubeface + tileNr);
+
+					submit(cm.getId(), StreetsideCache.Type.CUBEMAP_FRONT, ignoreDownload);
+
+				}
+			}
+		}
+	   break;
+   default:
+     submit(cm.getId(), StreetsideCache.Type.CUBEMAP_FRONT, ignoreDownload);
+     break;
+ }
+}*/
+
+/*public static void downloadCubemapRight(StreetsideImage cm, PICTURE pic) {
+	 switch (pic) {
+	   case CUBEMAP:
+		   for (int i = 0; i < 6; i++) {
+				for (int j = 0; j < 4; j++) {
+					for (int k = 0; k < 4; k++) {
+						String cubeface = CubemapUtils.getFaceNumberForCount(i);
+						String tileNr = CubemapUtils.rowCol2StreetsideCellAddressMap
+								.get(Integer.toString(j) + Integer.toString(k));
+						long tileId = Long.parseLong(cm.getId() + cubeface + tileNr);
+
+						submit(cm.getId(), StreetsideCache.Type.CUBEMAP_RIGHT, ignoreDownload);
+
+					}
+				}
+			}
+		   break;
+	   default:
+	     submit(cm.getId(), StreetsideCache.Type.CUBEMAP_RIGHT, ignoreDownload);
+	     break;
+	 }
+	}*/
+
+/*public static void downloadCubemapBack(StreetsideImage cm, PICTURE pic) {
+	 switch (pic) {
+	   case CUBEMAP:
+		   for (int i = 0; i < 6; i++) {
+				for (int j = 0; j < 4; j++) {
+					for (int k = 0; k < 4; k++) {
+						String cubeface = CubemapUtils.getFaceNumberForCount(i);
+						String tileNr = CubemapUtils.rowCol2StreetsideCellAddressMap
+								.get(Integer.toString(j) + Integer.toString(k));
+						long tileId = Long.parseLong(cm.getId() + cubeface + tileNr);
+
+						submit(cm.getId(), StreetsideCache.Type.CUBEMAP_BACK, ignoreDownload);
+
+					}
+				}
+			}
+		   break;
+	   default:
+	     submit(cm.getId(), StreetsideCache.Type.CUBEMAP_BACK, ignoreDownload);
+	     break;
+	 }
+	}*/
+
+/*public static void downloadCubemapLeft(StreetsideImage cm, PICTURE pic) {
+	 switch (pic) {
+	   case CUBEMAP:
+		   for (int i = 0; i < 6; i++) {
+				for (int j = 0; j < 4; j++) {
+					for (int k = 0; k < 4; k++) {
+						String cubeface = CubemapUtils.getFaceNumberForCount(i);
+						String tileNr = CubemapUtils.rowCol2StreetsideCellAddressMap
+								.get(Integer.toString(j) + Integer.toString(k));
+						long tileId = Long.parseLong(cm.getId() + cubeface + tileNr);
+
+						submit(cm.getId(), StreetsideCache.Type.CUBEMAP_LEFT, ignoreDownload);
+
+					}
+				}
+			}
+		   break;
+	   default:
+	     submit(cm.getId(), StreetsideCache.Type.CUBEMAP_LEFT, ignoreDownload);
+	     break;
+	 }
+	}*/
+
+/*public static void downloadCubemapUp(StreetsideImage cm, PICTURE pic) {
+	 switch (pic) {
+	   case CUBEMAP:
+		   for (int i = 0; i < 6; i++) {
+				for (int j = 0; j < 4; j++) {
+					for (int k = 0; k < 4; k++) {
+						String cubeface = CubemapUtils.getFaceNumberForCount(i);
+						String tileNr = CubemapUtils.rowCol2StreetsideCellAddressMap
+								.get(Integer.toString(j) + Integer.toString(k));
+						long tileId = Long.parseLong(cm.getId() + cubeface + tileNr);
+
+						submit(cm.getId(), StreetsideCache.Type.CUBEMAP_UP, ignoreDownload);
+
+					}
+				}
+			}
+		   break;
+	   default:
+	     submit(cm.getId(), StreetsideCache.Type.CUBEMAP_UP, ignoreDownload);
+	     break;
+	 }
+	}*/
+
+/*public static void downloadCubemapDown(StreetsideImage cm, PICTURE pic) {
+	 switch (pic) {
+	   case CUBEMAP:
+		   for (int i = 0; i < 6; i++) {
+				for (int j = 0; j < 4; j++) {
+					for (int k = 0; k < 4; k++) {
+						String cubeface = CubemapUtils.getFaceNumberForCount(i);
+						String tileNr = CubemapUtils.rowCol2StreetsideCellAddressMap
+								.get(Integer.toString(j) + Integer.toString(k));
+						long tileId = Long.parseLong(cm.getId() + cubeface + tileNr);
+
+						submit(cm.getId(), StreetsideCache.Type.CUBEMAP_DOWN, ignoreDownload);
+
+					}
+				}
+			}
+		   break;
+	   default:
+	     submit(cm.getId(), StreetsideCache.Type.CUBEMAP_DOWN, ignoreDownload);
+	     break;
+	 }
+	}*/
+
+/**
+* Requests the picture with the given key and quality and uses the given
+* listener.
+*
+* @param key
+*          The key of the picture to be requested.
+* @param type
+*          The quality of the picture to be requested.
+* @param lis
+*          The listener that is going to receive the picture.
+*/
+public static void submit(String key, StreetsideCache.Type type,
+   ICachedLoaderListener lis) {
+ try {
+   new StreetsideCache(key, type).submit(lis, false);
+ } catch (IOException e) {
+   Logging.error(e);
+ }
+}
+
+private static class IgnoreDownload implements ICachedLoaderListener {
+
+ @Override
+ public void loadingFinished(CacheEntry arg0, CacheEntryAttributes arg1, LoadResult arg2) {
+   // Ignore download
+ }
+}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/Caches.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/Caches.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/Caches.java	(revision 34317)
@@ -0,0 +1,158 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.cache;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+
+import javax.swing.ImageIcon;
+
+import org.apache.commons.jcs.access.CacheAccess;
+import org.apache.commons.jcs.engine.behavior.IElementAttributes;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;
+import org.openstreetmap.josm.data.cache.JCSCacheManager;
+import org.openstreetmap.josm.plugins.streetside.model.UserProfile;
+import org.openstreetmap.josm.tools.Logging;
+
+public final class Caches {
+
+	private Caches() {
+		// Private constructor to avoid instantiation
+	}
+
+	public static File getCacheDirectory() {
+		final File f = new File(Main.pref.getPluginsDirectory().getPath() + "/MicrosoftStreetside/cache");
+		if (!f.exists()) {
+			f.mkdirs();
+		}
+		return f;
+	}
+
+	public abstract static class CacheProxy<K, V extends Serializable> {
+		private final CacheAccess<K, V> cache;
+
+		public CacheProxy() {
+			CacheAccess<K, V> c;
+			try {
+				c = createNewCache();
+			} catch (IOException e) {
+				Logging.log(Logging.LEVEL_WARN, "Could not initialize cache for " + getClass().getName(), e);
+				c = null;
+			}
+			cache = c;
+		}
+
+		protected abstract CacheAccess<K, V> createNewCache() throws IOException;
+
+		public V get(final K key) {
+			return cache == null ? null : cache.get(key);
+		}
+
+		public void put(final K key, final V value) {
+			if (cache != null) {
+				cache.put(key, value);
+			}
+		}
+	}
+
+	public static class ImageCache {
+		private static ImageCache instance;
+		private final CacheAccess<String, BufferedImageCacheEntry> cache;
+
+		public ImageCache() {
+			CacheAccess<String, BufferedImageCacheEntry> c;
+			try {
+				c = JCSCacheManager.getCache("streetside", 10, 10000, Caches.getCacheDirectory().getPath());
+			} catch (Exception e) {
+				Logging.log(Logging.LEVEL_WARN, "Could not initialize the Streetside image cache.", e);
+				c = null;
+			}
+			cache = c;
+		}
+
+		public CacheAccess<String, BufferedImageCacheEntry> getCache() {
+			return cache;
+		}
+
+		public static ImageCache getInstance() {
+			synchronized (ImageCache.class) {
+				if (ImageCache.instance == null) {
+					ImageCache.instance = new ImageCache();
+				}
+				return ImageCache.instance;
+			}
+		}
+	}
+
+	public static class CubemapCache {
+		private static CubemapCache instance;
+		private final CacheAccess<String, BufferedImageCacheEntry> cache;
+
+		public CubemapCache() {
+			CacheAccess<String, BufferedImageCacheEntry> c;
+			try {
+				c = JCSCacheManager.getCache("streetside", 10, 10000, Caches.getCacheDirectory().getPath());
+			} catch (Exception e) {
+				Logging.log(Logging.LEVEL_WARN, "Could not initialize the Streetside cubemap cache.", e);
+				c = null;
+			}
+			cache = c;
+		}
+
+		public CacheAccess<String, BufferedImageCacheEntry> getCache() {
+			return cache;
+		}
+
+		public static CubemapCache getInstance() {
+			synchronized (CubemapCache.class) {
+				if (CubemapCache.instance == null) {
+					CubemapCache.instance = new CubemapCache();
+				}
+				return CubemapCache.instance;
+			}
+		}
+	}
+
+	public static class MapObjectIconCache extends CacheProxy<String, ImageIcon> {
+		private static CacheProxy<String, ImageIcon> instance;
+
+		public static CacheProxy<String, ImageIcon> getInstance() {
+			synchronized (MapObjectIconCache.class) {
+				if (MapObjectIconCache.instance == null) {
+					MapObjectIconCache.instance = new MapObjectIconCache();
+				}
+				return MapObjectIconCache.instance;
+			}
+		}
+
+		@Override
+		protected CacheAccess<String, ImageIcon> createNewCache() throws IOException {
+			return JCSCacheManager.getCache("streetsideObjectIcons", 100, 1000, Caches.getCacheDirectory().getPath());
+		}
+	}
+
+	public static class UserProfileCache extends CacheProxy<String, UserProfile> {
+		private static CacheProxy<String, UserProfile> instance;
+
+		public static CacheProxy<String, UserProfile> getInstance() {
+			synchronized (UserProfileCache.class) {
+				if (UserProfileCache.instance == null) {
+					UserProfileCache.instance = new UserProfileCache();
+				}
+				return UserProfileCache.instance;
+			}
+		}
+
+		@Override
+		protected CacheAccess<String, UserProfile> createNewCache() throws IOException {
+			CacheAccess<String, UserProfile> cache =
+					JCSCacheManager.getCache("userProfile", 100, 1000, Caches.getCacheDirectory().getPath());
+			IElementAttributes atts = cache.getDefaultElementAttributes();
+			atts.setMaxLife(604_800_000); // Sets lifetime to 7 days (604800000=1000*60*60*24*7)
+			cache.setDefaultElementAttributes(atts);
+			return cache;
+		}
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/StreetsideCache.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/StreetsideCache.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/StreetsideCache.java	(revision 34317)
@@ -0,0 +1,102 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.cache;
+
+import java.net.URL;
+import java.util.HashMap;
+
+import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;
+import org.openstreetmap.josm.data.cache.JCSCachedTileLoaderJob;
+import org.openstreetmap.josm.data.imagery.TileJobOptions;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.VirtualEarth;
+
+/**
+ * Stores the downloaded pictures locally.
+ *
+ * @author nokutu
+ *
+ */
+public class StreetsideCache extends JCSCachedTileLoaderJob<String, BufferedImageCacheEntry> {
+
+	private final URL url;
+	private final String id;
+
+	/**
+	 * Types of images.
+	 *
+	 * @author nokutu
+	 */
+	public enum Type {
+		/** Full quality image */
+		FULL_IMAGE,
+		/** Low quality image */
+		THUMBNAIL,
+		/** cubemap faces */
+		// TODO: one class per cache/load required? really?!
+		CUBEMAP/*,
+		CUBEMAP_FRONT,
+		CUBEMAP_RIGHT,
+		CUBEMAP_BACK,
+		CUBEMAP_LEFT,
+		CUBEMAP_UP,
+		CUBEMAP_DOWN*/
+	}
+
+	/**
+	 * Main constructor.
+	 *
+	 * @param id
+	 *          The id of the image.
+	 * @param type
+	 *          The type of image that must be downloaded (THUMBNAIL or
+	 *          FULL_IMAGE).
+	 */
+	public StreetsideCache(final String id, final Type type) {
+		//ICacheAccess<String,BufferedImageCacheEntry>,TileJobOptions,ThreadPoolExecutor
+		// TODO: StreetsideCache.java:53: error: no suitable constructor found for JCSCachedTileLoaderJob(CacheAccess<String,BufferedImageCacheEntry>,int,int,HashMap<String,String>)
+//	    [javac] 		super(Caches.ImageCache.getInstance().getCache(), 50000, 50000, new HashMap<String,String>());
+//	    [javac] 		^
+//	    [javac]     constructor JCSCachedTileLoaderJob.JCSCachedTileLoaderJob(ICacheAccess<String,BufferedImageCacheEntry>,TileJobOptions,ThreadPoolExecutor) is not applicable
+//	    [javac]       (actual and formal argument lists differ in length)
+//	    [javac]     constructor JCSCachedTileLoaderJob.JCSCachedTileLoaderJob(ICacheAccess<String,BufferedImageCacheEntry>,TileJobOptions) is not applicable
+//	    [javac]       (actual and formal argument lists differ in length)
+
+		//super(Caches.ImageCache.getInstance().getCache(), 50000, 50000, new HashMap<String,String>());
+		//super(Caches.ImageCache.getInstance().getCache(),TileJobOptions,ThreadpoolExecutor)
+		//TileJobOptions tjo = ;
+		super(Caches.ImageCache.getInstance().getCache(),new TileJobOptions(50000, 50000, new HashMap<String,String>(),50000l));
+
+		if (id == null || type == null) {
+			this.id = null;
+			url = null;
+		} else {
+			//this.id = id + (type == Type.FULL_IMAGE ? ".FULL_IMAGE" : ".THUMBNAIL");
+			// Add an "01" to the Streetside imageId in order to get a frontal thumbnail image for the display
+			this.id = id;
+			url = VirtualEarth.streetsideTile(id, type == Type.THUMBNAIL);
+		}
+	}
+
+	@Override
+	public String getCacheKey() {
+		return id;
+	}
+
+	@Override
+	public URL getUrl() {
+		return url;
+	}
+
+	@Override
+	protected BufferedImageCacheEntry createCacheEntry(byte[] content) {
+		return new BufferedImageCacheEntry(content);
+	}
+
+	@Override
+	protected boolean isObjectLoadable() {
+		if (cacheData == null) {
+			return false;
+		}
+		final byte[] content = cacheData.getContent();
+		return content != null && content.length > 0;
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/package-info.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/package-info.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cache/package-info.java	(revision 34317)
@@ -0,0 +1,7 @@
+// License: GPL. For details, see LICENSE file.
+/**
+ * This package is all about caching resources downloaded from
+ * <a href="https://mapillary.com">mapillary.com</a>
+ * for faster access to those resources in the future.
+ */
+package org.openstreetmap.josm.plugins.streetside.cache;
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/CameraTransformer.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/CameraTransformer.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/CameraTransformer.java	(revision 34317)
@@ -0,0 +1,184 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.cubemap;
+
+/**
+ * @author Dub
+ */
+
+import javafx.scene.Group;
+import javafx.scene.transform.Rotate;
+import javafx.scene.transform.Scale;
+import javafx.scene.transform.Translate;
+
+@SuppressWarnings("restriction")
+public class CameraTransformer extends Group {
+
+	public enum RotateOrder {
+		XYZ, XZY, YXZ, YZX, ZXY, ZYX
+	}
+
+	public Translate t = new Translate();
+	public Translate p = new Translate();
+	public Translate ip = new Translate();
+	public Rotate rx = new Rotate();
+	{
+		rx.setAxis(Rotate.X_AXIS);
+	}
+	public Rotate ry = new Rotate();
+	{
+		ry.setAxis(Rotate.Y_AXIS);
+	}
+	public Rotate rz = new Rotate();
+	{
+		rz.setAxis(Rotate.Z_AXIS);
+	}
+	public Scale s = new Scale();
+
+	public CameraTransformer() {
+		super();
+		getTransforms().addAll(t, rz, ry, rx, s);
+	}
+
+	public CameraTransformer(CameraTransformer.RotateOrder rotateOrder) {
+		super();
+		switch (rotateOrder) {
+		case XYZ:
+			getTransforms().addAll(t, p, rz, ry, rx, s, ip);
+			break;
+		case XZY:
+			getTransforms().addAll(t, p, ry, rz, rx, s, ip);
+			break;
+		case YXZ:
+			getTransforms().addAll(t, p, rz, rx, ry, s, ip);
+			break;
+		case YZX:
+			getTransforms().addAll(t, p, rx, rz, ry, s, ip); // For Camera
+			break;
+		case ZXY:
+			getTransforms().addAll(t, p, ry, rx, rz, s, ip);
+			break;
+		case ZYX:
+			getTransforms().addAll(t, p, rx, ry, rz, s, ip);
+			break;
+		}
+	}
+
+	public void setTranslate(double x, double y, double z) {
+		t.setX(x);
+		t.setY(y);
+		t.setZ(z);
+	}
+
+	public void setTranslate(double x, double y) {
+		t.setX(x);
+		t.setY(y);
+	}
+
+	public void setTx(double x) {
+		t.setX(x);
+	}
+
+	public void setTy(double y) {
+		t.setY(y);
+	}
+
+	public void setTz(double z) {
+		t.setZ(z);
+	}
+
+	public void setRotate(double x, double y, double z) {
+		rx.setAngle(x);
+		ry.setAngle(y);
+		rz.setAngle(z);
+	}
+
+	public void setRotateX(double x) {
+		rx.setAngle(x);
+	}
+
+	public void setRotateY(double y) {
+		ry.setAngle(y);
+	}
+
+	public void setRotateZ(double z) {
+		rz.setAngle(z);
+	}
+
+	public void setRx(double x) {
+		rx.setAngle(x);
+	}
+
+	public void setRy(double y) {
+		ry.setAngle(y);
+	}
+
+	public void setRz(double z) {
+		rz.setAngle(z);
+	}
+
+	public void setScale(double scaleFactor) {
+		s.setX(scaleFactor);
+		s.setY(scaleFactor);
+		s.setZ(scaleFactor);
+	}
+
+	public void setScale(double x, double y, double z) {
+		s.setX(x);
+		s.setY(y);
+		s.setZ(z);
+	}
+
+	public void setSx(double x) {
+		s.setX(x);
+	}
+
+	public void setSy(double y) {
+		s.setY(y);
+	}
+
+	public void setSz(double z) {
+		s.setZ(z);
+	}
+
+	public void setPivot(double x, double y, double z) {
+		p.setX(x);
+		p.setY(y);
+		p.setZ(z);
+		ip.setX(-x);
+		ip.setY(-y);
+		ip.setZ(-z);
+	}
+
+	public void reset() {
+		t.setX(0.0);
+		t.setY(0.0);
+		t.setZ(0.0);
+		rx.setAngle(0.0);
+		ry.setAngle(0.0);
+		rz.setAngle(0.0);
+		s.setX(1.0);
+		s.setY(1.0);
+		s.setZ(1.0);
+		p.setX(0.0);
+		p.setY(0.0);
+		p.setZ(0.0);
+		ip.setX(0.0);
+		ip.setY(0.0);
+		ip.setZ(0.0);
+	}
+
+	public void resetTSP() {
+		t.setX(0.0);
+		t.setY(0.0);
+		t.setZ(0.0);
+		s.setX(1.0);
+		s.setY(1.0);
+		s.setZ(1.0);
+		p.setX(0.0);
+		p.setY(0.0);
+		p.setZ(0.0);
+		ip.setX(0.0);
+		ip.setY(0.0);
+		ip.setZ(0.0);
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/CubemapBuilder.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/CubemapBuilder.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/CubemapBuilder.java	(revision 34317)
@@ -0,0 +1,289 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.cubemap;
+
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideCubemap;
+import org.openstreetmap.josm.plugins.streetside.StreetsideDataListener;
+import org.openstreetmap.josm.plugins.streetside.gui.StreetsideViewerDialog;
+import org.openstreetmap.josm.plugins.streetside.gui.imageinfo.StreetsideViewerHelpPopup;
+import org.openstreetmap.josm.plugins.streetside.gui.imageinfo.StreetsideViewerPanel;
+import org.openstreetmap.josm.plugins.streetside.utils.CubemapBox;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.Logging;
+
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+
+@SuppressWarnings("restriction")
+public class CubemapBuilder implements ITileDownloadingTaskListener, StreetsideDataListener {
+
+	private static CubemapBuilder instance;
+	// TODO: Help Pop-up
+	private StreetsideViewerHelpPopup streetsideViewerHelp;
+	private StreetsideCubemap cubemap;
+	protected boolean cancelled;
+	private long startTime;
+
+	private CubemapBuilder() {
+		// private constructor to avoid instantiation
+	}
+
+	@Override
+	public void imagesAdded() {
+		// Do nothing
+	}
+
+	@Override
+	public void selectedImageChanged(StreetsideAbstractImage oldImage, StreetsideAbstractImage newImage) {
+		startTime = System.currentTimeMillis();
+
+		if (newImage != null) {
+
+			cubemap = null;
+			cubemap = new StreetsideCubemap(newImage.getId(), newImage.getLatLon(), newImage.getHe());
+			cubemap.setCd(newImage.getCd());
+
+			// download cubemap images in different threads and then subsequently
+			// set the cubeface images in JavaFX
+			downloadCubemapImages(cubemap.getId());
+		}
+	}
+
+	public void reload(String imageId) {
+		if (cubemap != null && imageId.equals(cubemap.getId())) {
+			CubemapBuilder.getInstance().getCubemap().resetFaces2TileMap();
+			downloadCubemapImages(imageId);
+		}
+	}
+
+	public void downloadCubemapImages(String imageId) {
+
+		final int maxCols = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get() ? 4 : 2;
+		final int maxRows = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get() ? 4 : 2;
+		final int maxThreadCount = 6 * maxCols * maxRows;
+
+		int fails = 0;
+
+		long startTime = System.currentTimeMillis();
+
+		try {
+
+			ExecutorService pool = Executors.newFixedThreadPool(maxThreadCount);
+			List<Callable<String>> tasks = new ArrayList<Callable<String>>(maxThreadCount);
+
+			// launch 4-tiled (low-res) downloading tasks . . .
+			if (!StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {
+				for (int i = 0; i < CubemapUtils.NUM_SIDES; i++) {
+					int tileNr = 0;
+					for (int j = 0; j < maxCols; j++) {
+						for (int k = 0; k < maxRows; k++) {
+
+							String tileId = String.valueOf(imageId + CubemapUtils.getFaceNumberForCount(i)
+									+ Integer.valueOf(tileNr++).toString());// + Integer.valueOf(k).toString()));
+							tasks.add(new TileDownloadingTask(tileId));
+							Logging.debug(
+									I18n.tr("Starting tile downloading task for imageId {0}, cubeface {1}, tileNr {2}",
+											tileId, CubemapUtils.getFaceNumberForCount(i), String.valueOf(tileNr)));
+						}
+					}
+				}
+
+				List<Future<String>> results = pool.invokeAll(tasks);
+				for (Future<String> ff : results) {
+
+					Logging.debug(I18n.tr("Completed tile downloading task {0} in {1}", ff.get(),
+							CubemapUtils.msToString(startTime - System.currentTimeMillis())));
+				}
+
+				// launch 16-tiled (high-res) downloading tasks
+			} else if (StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {
+				for (int i = 0; i < CubemapUtils.NUM_SIDES; i++) {
+					for (int j = 0; j < maxCols; j++) {
+						for (int k = 0; k < maxRows; k++) {
+
+							String tileId = String.valueOf(imageId + CubemapUtils.getFaceNumberForCount(i)
+									+ String.valueOf(Integer.valueOf(j).toString() + Integer.valueOf(k).toString()));
+							tasks.add(new TileDownloadingTask(tileId));
+							Logging.debug(
+									I18n.tr("Starting tile downloading task for imageId {0}, cubeface {1}, tileID {2}",
+											imageId, CubemapUtils.getFaceNumberForCount(i), tileId));
+						}
+					}
+				}
+
+				List<Future<String>> results = pool.invokeAll(tasks);
+				for (Future<String> ff : results) {
+					Logging.info(I18n.tr("Completed tile downloading task {0} in {1}", ff.get(),
+							CubemapUtils.msToString(startTime - System.currentTimeMillis())));
+				}
+			}
+		} catch (Exception ee) {
+			fails++;
+			Logging.error("Error loading tile for image {0}", imageId);
+			ee.printStackTrace();
+		}
+
+		long stopTime = System.currentTimeMillis();
+		long runTime = stopTime - startTime;
+
+		Logging.info(I18n.tr("Tile imagery downloading tasks completed in {0}", CubemapUtils.msToString(runTime)));
+
+		if (fails > 0) {
+			Logging.error(I18n.tr("{0} downloading tasks failed.", Integer.valueOf(fails)));
+		}
+
+	}
+
+	@Override
+	public void tileAdded(String tileId) {
+		// determine whether four tiles have been set for each of the
+		// six cubemap faces. If so, build the images for the faces
+		// and set the views in the cubemap box.
+
+		int tileCount = 0;
+
+		for (int i = 0; i < CubemapUtils.NUM_SIDES; i++) {
+			String faceNumber = CubemapUtils.getFaceNumberForCount(i);
+			Map<String, BufferedImage> faceTileImages = CubemapBuilder.getInstance().getCubemap().getFace2TilesMap()
+					.get(faceNumber);
+			tileCount += faceTileImages.values().size();
+		}
+
+		int maxCols = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get() ? 4 : 2;
+		int maxRows = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get() ? 4 : 2;
+
+		if (tileCount == (CubemapUtils.NUM_SIDES * maxCols * maxRows)) {
+			Logging.info(I18n.tr("{0} tile images ready for building cumbemap faces for cubemap {0}", tileCount,
+					CubemapBuilder.getInstance().getCubemap().getId()));
+
+			buildCubemapFaces();
+		} else {
+			Logging.info(I18n.tr("{0} tile images received for cubemap {1}", Integer.valueOf(tileCount).toString(),
+					CubemapBuilder.getInstance().getCubemap().getId()));
+		}
+	}
+
+	private void buildCubemapFaces() {
+		CubemapBox cmb = StreetsideViewerDialog.getInstance().getStreetsideViewerPanel().getCubemapBox();
+		ImageView[] views = cmb.getViews();
+
+		final int maxCols = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get() ? 4 : 2;
+		final int maxRows = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get() ? 4 : 2;
+
+		Image finalImages[] = new Image[CubemapUtils.NUM_SIDES];
+
+		// build 4-tiled cubemap faces and crop buffers
+		if (!StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {
+			for (int i = 0; i < CubemapUtils.NUM_SIDES; i++) {
+
+				Map<String, BufferedImage> tileImages = CubemapBuilder.getInstance().getCubemap().getFace2TilesMap()
+						.get(CubemapUtils.getFaceNumberForCount(i));
+				BufferedImage[] faceTileImages = new BufferedImage[maxCols * maxRows];
+
+				for (int j = 0; j < (maxCols * maxRows); j++) {
+					String tileId = String.valueOf(getCubemap().getId() + CubemapUtils.getFaceNumberForCount(i)
+							+ Integer.valueOf(j).toString());
+					BufferedImage currentTile = tileImages.get(tileId);
+
+					faceTileImages[j] = currentTile;
+				}
+
+				BufferedImage finalImg = GraphicsUtils.buildMultiTiledCubemapFaceImage(faceTileImages);
+
+				// rotate top cubeface 180 degrees - misalignment workaround
+				if (i == 4) {
+					finalImg = GraphicsUtils.rotateImage(finalImg);
+				}
+				finalImages[i] = GraphicsUtils.convertBufferedImage2JavaFXImage(finalImg);
+			}
+			// build 16-tiled cubemap faces and crop buffers
+		} else if (StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {
+			for (int i = 0; i < CubemapUtils.NUM_SIDES; i++) {
+
+				int tileCount = 0;
+
+				Map<String, Map<String, BufferedImage>> face2TilesMap = CubemapBuilder.getInstance().getCubemap()
+						.getFace2TilesMap();
+				Map<String, BufferedImage> tileImages = face2TilesMap.get(CubemapUtils.getFaceNumberForCount(i));
+				BufferedImage[] faceTileImages = new BufferedImage[StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY
+						.get() ? 16 : 4];
+
+				for (int j = 0; j < maxCols; j++) {
+					for (int k = 0; k < maxRows; k++) {
+						String tileId = String.valueOf(getCubemap().getId() + CubemapUtils.getFaceNumberForCount(i)
+								+ CubemapUtils.convertDoubleCountNrto16TileNr(
+										String.valueOf(Integer.valueOf(j).toString() + Integer.valueOf(k).toString())));
+						BufferedImage currentTile = tileImages.get(tileId);
+						faceTileImages[tileCount++] = currentTile;
+					}
+				}
+				BufferedImage finalImg = GraphicsUtils.buildMultiTiledCubemapFaceImage(faceTileImages);
+				// rotate top cubeface 180 degrees - misalignment workaround
+				if (i == 4) {
+					finalImg = GraphicsUtils.rotateImage(finalImg);
+				}
+				finalImages[i] = GraphicsUtils.convertBufferedImage2JavaFXImage(finalImg);
+			}
+		}
+
+		for (int i = 0; i < CubemapUtils.NUM_SIDES; i++) {
+			views[i].setImage(finalImages[i]);
+		}
+
+		StreetsideViewerDialog.getInstance().getStreetsideViewerPanel().revalidate();
+		StreetsideViewerDialog.getInstance().getStreetsideViewerPanel().repaint();
+		StreetsideViewerPanel.getThreeSixtyDegreeViewerPanel().revalidate();
+		StreetsideViewerPanel.getThreeSixtyDegreeViewerPanel().repaint();
+
+		long endTime = System.currentTimeMillis();
+		long runTime = endTime - startTime;
+		Logging.info(I18n.tr("Completed downloading, assembling and setting cubemap imagery for cubemap {0} in {1}",
+				cubemap.getId(), CubemapUtils.msToString(runTime)));
+	}
+
+	/**
+	 * @return the cubemap
+	 */
+	public synchronized StreetsideCubemap getCubemap() {
+		return cubemap;
+	}
+
+	/**
+	 * @param cubemap
+	 *            the cubemap to set
+	 */
+	public static void setCubemap(StreetsideCubemap cubemap) {
+		CubemapBuilder.getInstance().cubemap = cubemap;
+	}
+
+	public static CubemapBuilder getInstance() {
+		if (instance == null) {
+			instance = new CubemapBuilder();
+		}
+		return instance;
+	}
+
+	/**
+	 * @return true, iff the singleton instance is present
+	 */
+	public static boolean hasInstance() {
+		return CubemapBuilder.instance != null;
+	}
+
+	/**
+	 * Destroys the unique instance of the class.
+	 */
+	public static synchronized void destroyInstance() {
+		CubemapBuilder.instance = null;
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/CubemapUtils.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/CubemapUtils.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/CubemapUtils.java	(revision 34317)
@@ -0,0 +1,283 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.cubemap;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.Logging;
+
+public class CubemapUtils {
+
+	public enum CubefaceType {
+		    ONE(1),
+		    FOUR(4),
+		    SIXTEEN(16);
+
+		    private int value;
+		    private static Map<Integer, CubefaceType> map = new HashMap<>();
+
+		    private CubefaceType(int value) {
+		        this.value = value;
+		    }
+
+		    static {
+		        for (CubefaceType cubefaceType : CubefaceType.values()) {
+		            map.put(cubefaceType.value, cubefaceType);
+		        }
+		    }
+
+		    public static CubefaceType valueOf(int cubefaceType) {
+		        return (CubefaceType) map.get(cubefaceType);
+		    }
+
+		    public int getValue() {
+		        return value;
+		    }
+		}
+
+	public static enum CubemapFaces {
+		FRONT("01"),
+		RIGHT("02"),
+		BACK("03"),
+		LEFT("10"),
+		UP("11"),
+		DOWN("12");
+
+		public static Stream<CubemapFaces> stream() {
+			return Stream.of(CubemapFaces.values());
+		}
+
+		private final String value;
+
+		CubemapFaces(String value) {
+			this.value = value;
+		}
+
+		public String getValue() {
+			return value;
+		}
+	}
+
+	public static Map<String[],String> directionConversion = new HashMap<>();
+
+	// numerical base for decimal conversion (quaternary in the case of Streetside)
+	private static final int NUM_BASE = 4;
+	public static final String IMPORTED_ID = "00000000";
+	public static final int NUM_SIDES = 6;
+
+	public static Map<String,String> rowCol2StreetsideCellAddressMap = null;
+
+	// Intialize utility map for storing row to Streetside cell number conversions
+	static {
+
+		CubemapUtils.rowCol2StreetsideCellAddressMap = new HashMap<>();
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("00","00");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("01","01");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("02","10");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("03","11");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("10","02");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("11","03");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("12","12");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("13","13");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("20","20");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("21","21");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("22","30");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("23","31");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("30","22");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("31","23");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("32","32");
+		CubemapUtils.rowCol2StreetsideCellAddressMap.put("33","33");
+	}
+
+	public static String convertDecimal2Quaternary(long inputNum) {
+		String res = null;
+		final StringBuilder sb = new StringBuilder();
+
+		while (inputNum > 0) {
+			sb.append(inputNum % CubemapUtils.NUM_BASE);
+			inputNum /= CubemapUtils.NUM_BASE;
+		}
+
+		sb.append("0");
+		res = sb.reverse().toString();
+
+		return res;
+	}
+
+	public static String convertQuaternary2Decimal(String inputNum) {
+		int len = inputNum.length();
+		int power = 1; // Initialize power of base
+		int num = 0; // Initialize result
+		int base = 4; // This could be used for any base, not just quad
+
+		// Decimal equivalent is str[len-1]*1 +
+		// str[len-1]*base + str[len-1]*(base^2) + ...
+		for (int i = len - 1; i >= 0; i--) {
+			// A digit in input number must be
+			// less than number's base
+			int current = Integer.valueOf(String.valueOf(inputNum.substring(i,i+1)));
+			if ( current >= 4) {
+				Logging.error(I18n.tr("Invalid bubbleId {0}", inputNum));
+				return "-1";
+			}
+
+			num += Integer.valueOf(inputNum.charAt(i)).intValue() * power;
+			power = power * base;
+		}
+
+		return Integer.toString(num);
+	}
+
+	public static String getFaceNumberForCount(int count) {
+		final String res;
+
+		switch (count) {
+		case 0:
+			res = CubemapFaces.FRONT.getValue();
+			break;
+		case 1:
+			res = CubemapFaces.RIGHT.getValue();
+			break;
+		case 2:
+			res = CubemapFaces.BACK.getValue();
+			break;
+		case 3:
+			res = CubemapFaces.LEFT.getValue();
+			break;
+		case 4:
+			res = CubemapFaces.UP.getValue();
+			break;
+		case 5:
+			res = CubemapFaces.DOWN.getValue();
+			break;
+		default:
+			res = null;
+			break;
+		}
+		return res;
+	}
+
+	public static int getTileWidth() {
+		// 4-tiled cubemap imagery has a 2-pixel overlap; 16-tiled has a 1-pixel
+		// overlap
+		if (!StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {
+			return 255;
+		} else {
+			return 254;
+		}
+	}
+
+	public static int getTileHeight() {
+		// 4-tiled cubemap imagery has a 2-pixel overlap; 16-tiled has a 1-pixel
+		// overlap
+		if(!StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {
+			return 255;
+		} else {
+			return 254;
+		}
+	}
+
+	public static int getCount4FaceNumber(String faceString) {
+
+		final int tileAddress;
+
+		switch (faceString) {
+        // back
+		case "03":  tileAddress = 0;
+                 break;
+        // down
+        case "12":  tileAddress = 1;
+                 break;
+        // front
+        case "01":  tileAddress = 2;
+                 break;
+        // left
+        case "10":  tileAddress = 3;
+                 break;
+        // right
+        case "02":  tileAddress = 4;
+                 break;
+        // up
+        case "11":  tileAddress = 5;
+                 break;
+        default: tileAddress = 6;
+                 break;
+		}
+
+		return tileAddress;
+	}
+
+	public static String getFaceIdFromTileId(String tileId) {
+		// magic numbers - the face id is contained in the 16th and 17th positions
+		return tileId.substring(16, 18);
+	}
+
+	public static String msToString(long ms) {
+        long totalSecs = ms/1000;
+        long hours = (totalSecs / 3600);
+        long mins = (totalSecs / 60) % 60;
+        long secs = totalSecs % 60;
+        String minsString = (mins == 0)
+            ? "00"
+            : ((mins < 10)
+               ? "0" + mins
+               : "" + mins);
+        String secsString = (secs == 0)
+            ? "00"
+            : ((secs < 10)
+               ? "0" + secs
+               : "" + secs);
+        if (hours > 0)
+            return hours + ":" + minsString + ":" + secsString;
+        else if (mins > 0)
+            return mins + ":" + secsString;
+        else return ":" + secsString;
+    }
+
+	public static String convertDoubleCountNrto16TileNr(String countNr) {
+		String tileAddress;
+
+		switch (countNr) {
+        case "00":  tileAddress = "00";
+                 break;
+        case "01":  tileAddress = "01";
+                 break;
+        case "02":  tileAddress = "10";
+                 break;
+        case "03":  tileAddress = "11";
+                 break;
+        case "10":  tileAddress = "02";
+                 break;
+        case "11":  tileAddress = "03";
+                 break;
+        case "12":  tileAddress = "12";
+                 break;
+        case "13":  tileAddress = "13";
+                 break;
+        case "20":  tileAddress = "20";
+                 break;
+        case "21":  tileAddress = "21";
+                 break;
+        case "22":  tileAddress = "30";
+                 break;
+        case "23":  tileAddress = "31";
+        		break;
+        case "30":  tileAddress = "22";
+           break;
+        case "31":  tileAddress = "23";
+           break;
+        case "32":  tileAddress = "32";
+           break;
+        case "33":  tileAddress = "33";
+           break;
+        // shouldn't happen
+        default: tileAddress = null;
+                 break;
+		}
+
+		return tileAddress;
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/GraphicsUtils.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/GraphicsUtils.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/GraphicsUtils.java	(revision 34317)
@@ -0,0 +1,130 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.cubemap;
+
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.tools.Logging;
+
+import javafx.application.Platform;
+import javafx.scene.image.PixelWriter;
+import javafx.scene.image.WritableImage;
+
+@SuppressWarnings({ "restriction"})
+public class GraphicsUtils {
+
+	public static javafx.scene.image.Image convertBufferedImage2JavaFXImage(BufferedImage bf) {
+		WritableImage wr = null;
+		if (bf != null) {
+			wr = new WritableImage(bf.getWidth(), bf.getHeight());
+			PixelWriter pw = wr.getPixelWriter();
+			for (int x = 0; x < bf.getWidth(); x++) {
+				for (int y = 0; y < bf.getHeight(); y++) {
+					pw.setArgb(x, y, bf.getRGB(x, y));
+				}
+			}
+		}
+		return wr;
+	}
+
+	public static class PlatformHelper {
+
+        public static void run(Runnable treatment) {
+            if(treatment == null) throw new IllegalArgumentException("The treatment to perform can not be null");
+
+            if(Platform.isFxApplicationThread()) treatment.run();
+            else Platform.runLater(treatment);
+        }
+    }
+
+	public static BufferedImage buildMultiTiledCubemapFaceImage(BufferedImage[] tiles) {
+
+		BufferedImage res = null;
+
+		int pixelBuffer = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?2:1;
+
+		tiles = cropMultiTiledImages(tiles, pixelBuffer);
+
+		int rows = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?4:2; //we assume the no. of rows and cols are known and each chunk has equal width and height
+        int cols = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?4:2;
+
+        int chunkWidth, chunkHeight;
+
+        chunkWidth = tiles[0].getWidth();
+        chunkHeight = tiles[0].getHeight();
+
+        //Initializing the final image
+        BufferedImage img = new BufferedImage(chunkWidth*cols, chunkHeight*rows, BufferedImage.TYPE_INT_ARGB);
+
+        int num = 0;
+        for (int i = 0; i < rows; i++) {
+            for (int j = 0; j < cols; j++) {
+                // TODO: this makes the image a mirror image. why!?!
+            	img.createGraphics().drawImage(tiles[num], chunkWidth * j, chunkHeight * i, null);
+
+            	// TODO: remove file test!
+            	/*try {
+        			ImageIO.write(img, "jpeg", new File("/Users/renerr18/Desktop/TileImagesTest/tile16b" + Long.valueOf(System.currentTimeMillis()).toString() + "createGraphicsAfter.jpeg"));
+        			//ImageIO.write(res[i], "jpeg", outputfileAfter);
+        		} catch (IOException e) {
+        			// TODO Auto-generated catch block
+        			e.printStackTrace();
+        		}*/
+
+                int width = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510;
+                int height = StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510;
+
+                // BufferedImage for mirror image
+                res = new BufferedImage(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510, StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()?1014:510,
+                                                BufferedImage.TYPE_INT_ARGB);
+
+                // Create mirror image pixel by pixel
+                for (int y = 0; y < height; y++)
+                {
+                    for (int lx = 0, rx = width - 1; lx < width; lx++, rx--)
+                    {
+                        // lx starts from the left side of the image
+                        // rx starts from the right side of the image
+                        // lx is used since we are getting pixel from left side
+                        // rx is used to set from right side
+                        // get source pixel value
+                        int p = img.getRGB(lx, y);
+
+                        // set mirror image pixel value
+                        res.setRGB(rx, y, p);
+                    }
+                }
+                num++;
+            }
+        }
+
+        Logging.info("Image concatenated.....");
+
+        return res;
+	}
+
+	public static BufferedImage rotateImage(BufferedImage bufImg) {
+		AffineTransform tx = AffineTransform.getScaleInstance(-1, -1);
+	    tx.translate(-bufImg.getWidth(null), -bufImg.getHeight(null));
+	    AffineTransformOp op = new AffineTransformOp(tx,
+	        AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
+	    bufImg = op.filter(bufImg, null);
+	    return bufImg;
+	}
+
+	private static BufferedImage[] cropMultiTiledImages(BufferedImage[] tiles, int pixelBuffer) {
+
+		BufferedImage[] res = new BufferedImage[tiles.length];
+
+			for(int i=0; i<tiles.length;i++) {
+				if(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {
+					res[i] = tiles[i].getSubimage(pixelBuffer, pixelBuffer, 256-pixelBuffer, 256-pixelBuffer);
+				} else {
+					res[i] = tiles[i].getSubimage(pixelBuffer, pixelBuffer, 256-pixelBuffer, 256-pixelBuffer);
+				}
+			}
+		return res;
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/ITileDownloadingTaskListener.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/ITileDownloadingTaskListener.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/ITileDownloadingTaskListener.java	(revision 34317)
@@ -0,0 +1,17 @@
+//License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.cubemap;
+
+/**
+* Interface for listeners of the class {@link StreetsideData}.
+*
+* @author renerr18
+*
+*/
+public interface ITileDownloadingTaskListener {
+
+/**
+* Fired when a cubemap tile image is downloaded by a download worker.
+*
+*/
+void tileAdded(String imageId);
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/TileDownloadingTask.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/TileDownloadingTask.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/cubemap/TileDownloadingTask.java	(revision 34317)
@@ -0,0 +1,132 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.cubemap;
+
+import java.awt.image.BufferedImage;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import javax.imageio.ImageIO;
+
+import org.openstreetmap.josm.plugins.streetside.cache.StreetsideCache;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.Logging;
+
+import us.monoid.web.Resty;
+
+public class TileDownloadingTask implements Callable<String> {
+
+	private String tileId;
+	private final long startTime = System.currentTimeMillis();
+	private StreetsideCache cache;
+	protected CubemapBuilder cb;
+
+	/**
+	   * Listeners of the class.
+	   */
+    private final List<ITileDownloadingTaskListener> listeners = new CopyOnWriteArrayList<>();
+
+	boolean cancelled = false;
+
+	public TileDownloadingTask(String id) {
+		tileId = id;
+		cb = CubemapBuilder.getInstance();
+		addListener(CubemapBuilder.getInstance());
+	}
+
+	/**
+	   * Adds a new listener.
+	   *
+	   * @param lis Listener to be added.
+	   */
+	public final void addListener(final ITileDownloadingTaskListener lis) {
+	    listeners.add(lis);
+	}
+
+	/**
+	 * @return the tileId
+	 */
+	public String getId() {
+		return tileId;
+	}
+
+	/**
+	 * @param tileId the tileId to set
+	 */
+	public void setId(String id) {
+		tileId = id;
+	}
+
+	/**
+	 * @return the cache
+	 */
+	public StreetsideCache getCache() {
+		return cache;
+	}
+
+	/**
+	 * @param cache the cache to set
+	 */
+	public void setCache(StreetsideCache cache) {
+		this.cache = cache;
+	}
+
+	/**
+	 * @return the cb
+	 */
+	public CubemapBuilder getCb() {
+		return cb;
+	}
+
+	/**
+	 * @param cb the cb to set
+	 */
+	public void setCb(CubemapBuilder cb) {
+		this.cb = cb;
+	}
+
+	/**
+	 * @param cancelled the cancelled to set
+	 */
+	public void setCancelled(boolean cancelled) {
+		this.cancelled = cancelled;
+	}
+
+	@Override
+	public String call() throws Exception {
+
+		BufferedImage img = ImageIO.read(new Resty().bytes(
+				StreetsideURL.VirtualEarth.streetsideTile(tileId, false).toExternalForm())
+				.stream());
+
+		if (img == null) {
+			Logging.error(I18n.tr("Download of BufferedImage {0} is null!", tileId));
+		}
+
+		String faceId = CubemapUtils.getFaceIdFromTileId(tileId);
+
+		Map<String, Map<String, BufferedImage>> faces2TilesMap = CubemapBuilder
+				.getInstance().getCubemap().getFace2TilesMap();
+
+		if(faces2TilesMap.get(faceId)==null) {
+			faces2TilesMap.put(faceId, new HashMap<String,BufferedImage>());
+		}
+		faces2TilesMap.get(faceId).put(tileId, img);
+
+		fireTileAdded(tileId);
+
+		long endTime = System.currentTimeMillis();
+		long runTime = startTime - endTime;
+		Logging.debug("Loaded image for tile {0} in {1} seconds", tileId, CubemapUtils.msToString(runTime));
+
+		return tileId;
+	}
+
+	private void fireTileAdded(String id) {
+	    listeners.stream().filter(Objects::nonNull).forEach(lis -> lis.tileAdded(id));
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideExportDialog.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideExportDialog.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideExportDialog.java	(revision 34317)
@@ -0,0 +1,162 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.AbstractAction;
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImportedImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+
+
+/**
+ * GUI for exporting images.
+ *
+ * @author nokutu
+ *
+ */
+public class StreetsideExportDialog extends JPanel implements ActionListener {
+
+  private static final long serialVersionUID = -2746815082016025516L;
+  /** Button to export all downloaded images. */
+  public final JRadioButton all;
+  /**
+   * Button to export all images in the sequence of the selected StreetsideImage.
+   */
+  public final JRadioButton sequence;
+  /**
+   * Button to export all images belonging to the selected
+   * {@link StreetsideImage} objects.
+   */
+  public final JRadioButton selected;
+  /** Button to rewrite all imported images. */
+  public final JRadioButton rewrite;
+  /** Group of button containing all the options. */
+  public final ButtonGroup group;
+  private final JButton choose;
+  private final JLabel path;
+  /** File chooser. */
+  public JFileChooser chooser;
+  private final JButton ok;
+
+  /**
+   * Main constructor.
+   *
+   * @param ok
+   *          The button for to OK option.
+   */
+  public StreetsideExportDialog(JButton ok) {
+    this.ok = ok;
+    ok.setEnabled(false);
+
+    setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
+
+    RewriteButtonAction action = new RewriteButtonAction(this);
+    this.group = new ButtonGroup();
+    this.all = new JRadioButton(action);
+    this.all.setText(tr("Export all images"));
+    this.sequence = new JRadioButton(action);
+    this.sequence.setText(tr("Export selected sequence"));
+    this.selected = new JRadioButton(action);
+    this.selected.setText(tr("Export selected images"));
+    this.rewrite = new JRadioButton(action);
+    this.rewrite.setText(tr("Rewrite imported images"));
+    this.group.add(this.all);
+    this.group.add(this.sequence);
+    this.group.add(this.selected);
+    this.group.add(this.rewrite);
+    // Some options are disabled depending on the circumstances
+    sequence.setEnabled(StreetsideLayer.getInstance().getData().getSelectedImage() instanceof StreetsideImage);
+    if (StreetsideLayer.getInstance().getData().getMultiSelectedImages().isEmpty()) {
+     this.selected.setEnabled(false);
+    }
+    this.rewrite.setEnabled(StreetsideLayer.getInstance().getData().getImages().parallelStream().anyMatch(img -> img instanceof StreetsideImportedImage));
+
+    this.path = new JLabel(tr("Select a directory"));
+    this.choose = new JButton(tr("Explore"));
+    this.choose.addActionListener(this);
+
+    // All options belong to the same JPanel so the are in line.
+    JPanel jpanel = new JPanel();
+    jpanel.setLayout(new BoxLayout(jpanel, BoxLayout.PAGE_AXIS));
+    jpanel.add(this.all);
+    jpanel.add(this.sequence);
+    jpanel.add(this.selected);
+    jpanel.add(this.rewrite);
+    jpanel.setAlignmentX(Component.CENTER_ALIGNMENT);
+    this.path.setAlignmentX(Component.CENTER_ALIGNMENT);
+    this.choose.setAlignmentX(Component.CENTER_ALIGNMENT);
+
+    add(jpanel);
+    add(this.path);
+    add(this.choose);
+  }
+
+  /**
+   * Creates the folder chooser GUI.
+   */
+  @Override
+  public void actionPerformed(ActionEvent e) {
+    this.chooser = new JFileChooser();
+    this.chooser.setCurrentDirectory(new java.io.File(System
+        .getProperty("user.home")));
+    this.chooser.setDialogTitle(tr("Select a directory"));
+    this.chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+    this.chooser.setAcceptAllFileFilterUsed(false);
+
+    if (this.chooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
+      this.path.setText(this.chooser.getSelectedFile().toString());
+      this.updateUI();
+      this.ok.setEnabled(true);
+    }
+  }
+
+  /**
+   * Enables/disables some parts of the panel depending if the rewrite button is
+   * active.
+   *
+   * @author nokutu
+   *
+   */
+  public class RewriteButtonAction extends AbstractAction {
+
+    private static final long serialVersionUID = 1035332841101190301L;
+
+	private String lastPath;
+    private final StreetsideExportDialog dlg;
+
+    /**
+     * Main constructor.
+     *
+     * @param dlg
+     *          Parent dialog.
+     */
+    public RewriteButtonAction(StreetsideExportDialog dlg) {
+      this.dlg = dlg;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent arg0) {
+      StreetsideExportDialog.this.choose
+          .setEnabled(!StreetsideExportDialog.this.rewrite.isSelected());
+      if (StreetsideExportDialog.this.rewrite.isSelected()) {
+        this.lastPath = this.dlg.path.getText();
+        this.dlg.path.setText(" ");
+      } else if (this.lastPath != null) {
+        this.dlg.path.setText(this.lastPath);
+      }
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideImageDisplay.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideImageDisplay.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideImageDisplay.java	(revision 34317)
@@ -0,0 +1,553 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.event.MouseWheelEvent;
+import java.awt.event.MouseWheelListener;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.swing.JComponent;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.actions.StreetsideDownloadAction;
+import org.openstreetmap.josm.plugins.streetside.model.ImageDetection;
+import org.openstreetmap.josm.plugins.streetside.model.MapObject;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideColorScheme;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+
+
+/**
+ * This object is a responsible JComponent which lets you zoom and drag. It is
+ * included in a {@link StreetsideMainDialog} object.
+ *
+ * @author nokutu
+ * @see StreetsideImageDisplay
+ * @see StreetsideMainDialog
+ */
+public class StreetsideImageDisplay extends JComponent {
+
+  private static final long serialVersionUID = -3188274185432686201L;
+
+  private final Collection<ImageDetection> detections = new ArrayList<>();
+
+  /** The image currently displayed */
+  private volatile BufferedImage image;
+
+  /**
+   * The rectangle (in image coordinates) of the image that is visible. This
+   * rectangle is calculated each time the zoom is modified
+   */
+  private volatile Rectangle visibleRect;
+
+  /**
+   * When a selection is done, the rectangle of the selection (in image
+   * coordinates)
+   */
+  private Rectangle selectedRect;
+
+  private class ImgDisplayMouseListener implements MouseListener, MouseWheelListener, MouseMotionListener {
+    private boolean mouseIsDragging;
+    private long lastTimeForMousePoint;
+    private Point mousePointInImg;
+
+    /**
+     * Zoom in and out, trying to preserve the point of the image that was under
+     * the mouse cursor at the same place
+     */
+    @Override
+    public void mouseWheelMoved(MouseWheelEvent e) {
+      Image image;
+      Rectangle visibleRect;
+      synchronized (StreetsideImageDisplay.this) {
+        image = getImage();
+        visibleRect = StreetsideImageDisplay.this.visibleRect;
+      }
+      mouseIsDragging = false;
+      selectedRect = null;
+      if (image != null && Math.min(getSize().getWidth(), getSize().getHeight()) > 0) {
+        // Calculate the mouse cursor position in image coordinates, so that
+        // we can center the zoom
+        // on that mouse position.
+        // To avoid issues when the user tries to zoom in on the image
+        // borders, this point is not calculated
+        // again if there was less than 1.5seconds since the last event.
+        if (e.getWhen() - lastTimeForMousePoint > 1500 || mousePointInImg == null) {
+          lastTimeForMousePoint = e.getWhen();
+          mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
+        }
+        // Set the zoom to the visible rectangle in image coordinates
+        if (e.getWheelRotation() > 0) {
+          visibleRect.width = visibleRect.width * 3 / 2;
+          visibleRect.height = visibleRect.height * 3 / 2;
+        } else {
+          visibleRect.width = visibleRect.width * 2 / 3;
+          visibleRect.height = visibleRect.height * 2 / 3;
+        }
+        // Check that the zoom doesn't exceed 2:1
+        if (visibleRect.width < getSize().width / 2) {
+          visibleRect.width = getSize().width / 2;
+        }
+        if (visibleRect.height < getSize().height / 2) {
+          visibleRect.height = getSize().height / 2;
+        }
+        // Set the same ratio for the visible rectangle and the display area
+        int hFact = visibleRect.height * getSize().width;
+        int wFact = visibleRect.width * getSize().height;
+        if (hFact > wFact) {
+          visibleRect.width = hFact / getSize().height;
+        } else {
+          visibleRect.height = wFact / getSize().width;
+        }
+        // The size of the visible rectangle is limited by the image size.
+        checkVisibleRectSize(image, visibleRect);
+        // Set the position of the visible rectangle, so that the mouse
+        // cursor doesn't move on the image.
+        Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
+        visibleRect.x = mousePointInImg.x
+            + ((drawRect.x - e.getX()) * visibleRect.width) / drawRect.width;
+        visibleRect.y = mousePointInImg.y
+            + ((drawRect.y - e.getY()) * visibleRect.height) / drawRect.height;
+        // The position is also limited by the image size
+        checkVisibleRectPos(image, visibleRect);
+        synchronized (StreetsideImageDisplay.this) {
+          StreetsideImageDisplay.this.visibleRect = visibleRect;
+        }
+        StreetsideImageDisplay.this.repaint();
+      }
+    }
+
+    /** Center the display on the point that has been clicked */
+    @Override
+    public void mouseClicked(MouseEvent e) {
+      // Move the center to the clicked point.
+      Image image;
+      Rectangle visibleRect;
+      synchronized (StreetsideImageDisplay.this) {
+        image = getImage();
+        visibleRect = StreetsideImageDisplay.this.visibleRect;
+      }
+      if (image != null && Math.min(getSize().getWidth(), getSize().getHeight()) > 0) {
+        if (e.getButton() == StreetsideProperties.PICTURE_OPTION_BUTTON.get()) {
+          if (!StreetsideImageDisplay.this.visibleRect.equals(new Rectangle(0, 0, image.getWidth(null), image.getHeight(null)))) {
+            // Zooms to 1:1
+            StreetsideImageDisplay.this.visibleRect = new Rectangle(0, 0,
+                image.getWidth(null), image.getHeight(null));
+          } else {
+            // Zooms to best fit.
+            StreetsideImageDisplay.this.visibleRect = new Rectangle(
+                0,
+                (image.getHeight(null) - (image.getWidth(null) * getHeight()) / getWidth()) / 2,
+                image.getWidth(null),
+                (image.getWidth(null) * getHeight()) / getWidth()
+            );
+          }
+          StreetsideImageDisplay.this.repaint();
+          return;
+        } else if (e.getButton() != StreetsideProperties.PICTURE_DRAG_BUTTON.get()) {
+          return;
+        }
+        // Calculate the translation to set the clicked point the center of
+        // the view.
+        Point click = comp2imgCoord(visibleRect, e.getX(), e.getY());
+        Point center = getCenterImgCoord(visibleRect);
+        visibleRect.x += click.x - center.x;
+        visibleRect.y += click.y - center.y;
+        checkVisibleRectPos(image, visibleRect);
+        synchronized (StreetsideImageDisplay.this) {
+          StreetsideImageDisplay.this.visibleRect = visibleRect;
+        }
+        StreetsideImageDisplay.this.repaint();
+      }
+    }
+
+    /**
+     * Initialize the dragging, either with button 1 (simple dragging) or button
+     * 3 (selection of a picture part)
+     */
+    @Override
+    public void mousePressed(MouseEvent e) {
+      if (getImage() == null) {
+        mouseIsDragging = false;
+        selectedRect = null;
+        return;
+      }
+      Image image;
+      Rectangle visibleRect;
+      synchronized (StreetsideImageDisplay.this) {
+        image = StreetsideImageDisplay.this.image;
+        visibleRect = StreetsideImageDisplay.this.visibleRect;
+      }
+      if (image == null)
+        return;
+      if (e.getButton() == StreetsideProperties.PICTURE_DRAG_BUTTON.get()) {
+        mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
+        mouseIsDragging = true;
+        selectedRect = null;
+      } else if (e.getButton() == StreetsideProperties.PICTURE_ZOOM_BUTTON.get()) {
+        mousePointInImg = comp2imgCoord(visibleRect, e.getX(), e.getY());
+        checkPointInVisibleRect(mousePointInImg, visibleRect);
+        mouseIsDragging = false;
+        selectedRect = new Rectangle(mousePointInImg.x, mousePointInImg.y, 0, 0);
+        StreetsideImageDisplay.this.repaint();
+      } else {
+        mouseIsDragging = false;
+        selectedRect = null;
+      }
+    }
+
+    @Override
+    public void mouseDragged(MouseEvent e) {
+      if (!mouseIsDragging && selectedRect == null)
+        return;
+      Image image;
+      Rectangle visibleRect;
+      synchronized (StreetsideImageDisplay.this) {
+        image = getImage();
+        visibleRect = StreetsideImageDisplay.this.visibleRect;
+      }
+      if (image == null) {
+        mouseIsDragging = false;
+        selectedRect = null;
+        return;
+      }
+      if (mouseIsDragging) {
+        Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
+        visibleRect.x += mousePointInImg.x - p.x;
+        visibleRect.y += mousePointInImg.y - p.y;
+        checkVisibleRectPos(image, visibleRect);
+        synchronized (StreetsideImageDisplay.this) {
+          StreetsideImageDisplay.this.visibleRect = visibleRect;
+        }
+        StreetsideImageDisplay.this.repaint();
+      } else if (selectedRect != null) {
+        Point p = comp2imgCoord(visibleRect, e.getX(), e.getY());
+        checkPointInVisibleRect(p, visibleRect);
+        Rectangle rect = new Rectangle(p.x < mousePointInImg.x ? p.x
+            : mousePointInImg.x, p.y < mousePointInImg.y ? p.y
+            : mousePointInImg.y, p.x < mousePointInImg.x ? mousePointInImg.x
+            - p.x : p.x - mousePointInImg.x,
+            p.y < mousePointInImg.y ? mousePointInImg.y - p.y : p.y
+                - mousePointInImg.y);
+        checkVisibleRectSize(image, rect);
+        checkVisibleRectPos(image, rect);
+        selectedRect = rect;
+        StreetsideImageDisplay.this.repaint();
+      }
+    }
+
+    @Override
+    public void mouseReleased(MouseEvent e) {
+      if (!mouseIsDragging && selectedRect == null)
+        return;
+      Image image;
+      synchronized (StreetsideImageDisplay.this) {
+        image = getImage();
+      }
+      if (image == null) {
+        mouseIsDragging = false;
+        selectedRect = null;
+        return;
+      }
+      if (mouseIsDragging) {
+        mouseIsDragging = false;
+      } else if (selectedRect != null) {
+        int oldWidth = selectedRect.width;
+        int oldHeight = selectedRect.height;
+        // Check that the zoom doesn't exceed 2:1
+        if (selectedRect.width < getSize().width / 2) {
+        	selectedRect.width = getSize().width / 2;
+        }
+        if (selectedRect.height < getSize().height / 2) {
+        	selectedRect.height = getSize().height / 2;
+        }
+        // Set the same ratio for the visible rectangle and the display
+        // area
+        int hFact = selectedRect.height * getSize().width;
+        int wFact = selectedRect.width * getSize().height;
+        if (hFact > wFact) {
+          selectedRect.width = hFact / getSize().height;
+        } else {
+          selectedRect.height = wFact / getSize().width;
+        }
+        // Keep the center of the selection
+        if (selectedRect.width != oldWidth) {
+        	selectedRect.x -= (selectedRect.width - oldWidth) / 2;
+        }
+        if (selectedRect.height != oldHeight) {
+        	selectedRect.y -= (selectedRect.height - oldHeight) / 2;
+        }
+        checkVisibleRectSize(image, selectedRect);
+        checkVisibleRectPos(image, selectedRect);
+        synchronized (StreetsideImageDisplay.this) {
+          visibleRect = selectedRect;
+        }
+        selectedRect = null;
+        StreetsideImageDisplay.this.repaint();
+      }
+    }
+
+    @Override
+    public void mouseEntered(MouseEvent e) {
+      // Do nothing, method is enforced by MouseListener
+    }
+
+    @Override
+    public void mouseExited(MouseEvent e) {
+      // Do nothing, method is enforced by MouseListener
+    }
+
+    @Override
+    public void mouseMoved(MouseEvent e) {
+      // Do nothing, method is enforced by MouseListener
+    }
+
+    private void checkPointInVisibleRect(Point p, Rectangle visibleRect) {
+      if (p.x < visibleRect.x) {
+        p.x = visibleRect.x;
+      }
+      if (p.x > visibleRect.x + visibleRect.width) {
+        p.x = visibleRect.x + visibleRect.width;
+      }
+      if (p.y < visibleRect.y) {
+        p.y = visibleRect.y;
+      }
+      if (p.y > visibleRect.y + visibleRect.height) {
+        p.y = visibleRect.y + visibleRect.height;
+      }
+    }
+  }
+
+  /**
+   * Main constructor.
+   */
+  public StreetsideImageDisplay() {
+    ImgDisplayMouseListener mouseListener = new ImgDisplayMouseListener();
+    addMouseListener(mouseListener);
+    addMouseWheelListener(mouseListener);
+    addMouseMotionListener(mouseListener);
+
+    StreetsideProperties.SHOW_DETECTED_SIGNS.addListener(valChanged -> repaint());
+  }
+
+  /**
+   * Sets a new picture to be displayed.
+   *
+   * @param image The picture to be displayed.
+   * @param detections image detections
+   */
+  public void setImage(BufferedImage image, Collection<ImageDetection> detections) {
+    synchronized (this) {
+      this.image = image;
+      this.detections.clear();
+      if (detections != null) {
+        this.detections.addAll(detections);
+      }
+      selectedRect = null;
+      if (image != null)
+        visibleRect = new Rectangle(0, 0, image.getWidth(null),
+            image.getHeight(null));
+    }
+    repaint();
+  }
+
+  /**
+   * Returns the picture that is being displayed
+   *
+   * @return The picture that is being displayed.
+   */
+  public BufferedImage getImage() {
+    return image;
+  }
+
+  /**
+   * Paints the visible part of the picture.
+   */
+  @Override
+  public void paintComponent(Graphics g) {
+    Image image;
+    Rectangle visibleRect;
+    synchronized (this) {
+      image = this.image;
+      visibleRect = this.visibleRect;
+    }
+    if (image == null) {
+      g.setColor(Color.black);
+      String noImageStr = StreetsideLayer.hasInstance() ? tr("No image selected") : tr("Press \"{0}\" to download images", StreetsideDownloadAction.SHORTCUT.getKeyText());
+      Rectangle2D noImageSize = g.getFontMetrics(g.getFont()).getStringBounds(
+          noImageStr, g);
+      Dimension size = getSize();
+      g.drawString(noImageStr,
+          (int) ((size.width - noImageSize.getWidth()) / 2),
+          (int) ((size.height - noImageSize.getHeight()) / 2));
+    } else {
+      Rectangle target = calculateDrawImageRectangle(visibleRect);
+      g.drawImage(image, target.x, target.y, target.x + target.width, target.y
+          + target.height, visibleRect.x, visibleRect.y, visibleRect.x
+          + visibleRect.width, visibleRect.y + visibleRect.height, null);
+      if (selectedRect != null) {
+        Point topLeft = img2compCoord(visibleRect, selectedRect.x,
+            selectedRect.y);
+        Point bottomRight = img2compCoord(visibleRect, selectedRect.x
+            + selectedRect.width, selectedRect.y + selectedRect.height);
+        g.setColor(new Color(128, 128, 128, 180));
+        g.fillRect(target.x, target.y, target.width, topLeft.y - target.y);
+        g.fillRect(target.x, target.y, topLeft.x - target.x, target.height);
+        g.fillRect(bottomRight.x, target.y, target.x + target.width
+            - bottomRight.x, target.height);
+        g.fillRect(target.x, bottomRight.y, target.width, target.y
+            + target.height - bottomRight.y);
+        g.setColor(Color.black);
+        g.drawRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x,
+            bottomRight.y - topLeft.y);
+      }
+
+      if (StreetsideProperties.SHOW_DETECTED_SIGNS.get()) {
+        Point upperLeft = img2compCoord(visibleRect, 0, 0);
+        Point lowerRight = img2compCoord(visibleRect, getImage().getWidth(), getImage().getHeight());
+
+        // Transformation, which can convert you a Shape relative to the unit square to a Shape relative to the Component
+        AffineTransform unit2compTransform = AffineTransform.getTranslateInstance(upperLeft.getX(), upperLeft.getY());
+        unit2compTransform.concatenate(AffineTransform.getScaleInstance(lowerRight.getX() - upperLeft.getX(), lowerRight.getY() - upperLeft.getY()));
+
+        final Graphics2D g2d = (Graphics2D) g;
+        g2d.setStroke(new BasicStroke(2));
+        for (ImageDetection d : detections) {
+          final Shape shape = d.getShape().createTransformedShape(unit2compTransform);
+          g2d.setColor(d.isTrafficSign() ? StreetsideColorScheme.IMAGEDETECTION_TRAFFICSIGN : StreetsideColorScheme.IMAGEDETECTION_UNKNOWN);
+          g2d.draw(shape);
+          if (d.isTrafficSign()) {
+            g2d.drawImage(
+              MapObject.getIcon(d.getValue()).getImage(),
+              shape.getBounds().x, shape.getBounds().y,
+              shape.getBounds().width, shape.getBounds().height,
+              null
+            );
+          }
+        }
+      }
+    }
+  }
+
+  private Point img2compCoord(Rectangle visibleRect, int xImg, int yImg) {
+    Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
+    return new Point(drawRect.x + ((xImg - visibleRect.x) * drawRect.width)
+        / visibleRect.width, drawRect.y
+        + ((yImg - visibleRect.y) * drawRect.height) / visibleRect.height);
+  }
+
+  private Point comp2imgCoord(Rectangle visibleRect, int xComp, int yComp) {
+    Rectangle drawRect = calculateDrawImageRectangle(visibleRect);
+    return new Point(
+        visibleRect.x + ((xComp - drawRect.x) * visibleRect.width) / drawRect.width,
+        visibleRect.y + ((yComp - drawRect.y) * visibleRect.height) / drawRect.height
+    );
+  }
+
+  private static Point getCenterImgCoord(Rectangle visibleRect) {
+    return new Point(visibleRect.x + visibleRect.width / 2, visibleRect.y + visibleRect.height / 2);
+  }
+
+  private Rectangle calculateDrawImageRectangle(Rectangle visibleRect) {
+    return calculateDrawImageRectangle(visibleRect, new Rectangle(0, 0, getSize().width, getSize().height));
+  }
+
+  /**
+   * calculateDrawImageRectangle
+   *
+   * @param imgRect
+   *          the part of the image that should be drawn (in image coordinates)
+   * @param compRect
+   *          the part of the component where the image should be drawn (in
+   *          component coordinates)
+   * @return the part of compRect with the same width/height ratio as the image
+   */
+  private static Rectangle calculateDrawImageRectangle(Rectangle imgRect, Rectangle compRect) {
+    int x = 0;
+    int y = 0;
+    int w = compRect.width;
+    int h = compRect.height;
+    int wFact = w * imgRect.height;
+    int hFact = h * imgRect.width;
+    if (wFact != hFact) {
+      if (wFact > hFact) {
+        w = hFact / imgRect.height;
+        x = (compRect.width - w) / 2;
+      } else {
+        h = wFact / imgRect.width;
+        y = (compRect.height - h) / 2;
+      }
+    }
+    return new Rectangle(x + compRect.x, y + compRect.y, w, h);
+  }
+
+  /**
+   * Zooms to 1:1 and, if it is already in 1:1, to best fit.
+   */
+  public void zoomBestFitOrOne() {
+    Image image;
+    Rectangle visibleRect;
+    synchronized (this) {
+      image = this.image;
+      visibleRect = this.visibleRect;
+    }
+    if (image == null)
+      return;
+    if (visibleRect.width != image.getWidth(null)
+        || visibleRect.height != image.getHeight(null)) {
+      // The display is not at best fit. => Zoom to best fit
+      visibleRect = new Rectangle(0, 0, image.getWidth(null),
+          image.getHeight(null));
+    } else {
+      // The display is at best fit => zoom to 1:1
+      Point center = getCenterImgCoord(visibleRect);
+      visibleRect = new Rectangle(center.x - getWidth() / 2, center.y
+          - getHeight() / 2, getWidth(), getHeight());
+      checkVisibleRectPos(image, visibleRect);
+    }
+    synchronized (this) {
+      this.visibleRect = visibleRect;
+    }
+    repaint();
+  }
+
+  private static void checkVisibleRectPos(Image image, Rectangle visibleRect) {
+    if (visibleRect.x < 0) {
+      visibleRect.x = 0;
+    }
+    if (visibleRect.y < 0) {
+      visibleRect.y = 0;
+    }
+    if (visibleRect.x + visibleRect.width > image.getWidth(null)) {
+      visibleRect.x = image.getWidth(null) - visibleRect.width;
+    }
+    if (visibleRect.y + visibleRect.height > image.getHeight(null)) {
+      visibleRect.y = image.getHeight(null) - visibleRect.height;
+    }
+  }
+
+  private static void checkVisibleRectSize(Image image, Rectangle visibleRect) {
+    if (visibleRect.width > image.getWidth(null)) {
+      visibleRect.width = image.getWidth(null);
+    }
+    if (visibleRect.height > image.getHeight(null)) {
+      visibleRect.height = image.getHeight(null);
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideImageTreeCellRenderer.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideImageTreeCellRenderer.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideImageTreeCellRenderer.java	(revision 34317)
@@ -0,0 +1,29 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui;
+
+import java.awt.Component;
+
+import javax.swing.Icon;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+/**
+ * Renders an item in a {@link JTree} that represents a {@link StreetsideAbstractImage}.
+ */
+public class StreetsideImageTreeCellRenderer extends DefaultTreeCellRenderer {
+  private static final long serialVersionUID = 5359276673450659572L;
+
+  private static final Icon ICON = new ImageProvider("mapicon").setMaxSize(16).get();
+
+  @Override
+  public Component getTreeCellRendererComponent(
+    JTree tree, Object value, boolean sel, boolean expanded, boolean leaf, int row, boolean hasFocus
+  ) {
+    super.getTreeCellRendererComponent(tree, value.toString(), sel, expanded, leaf, row, hasFocus);
+    setIcon(ICON);
+    return this;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideMainDialog.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideMainDialog.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideMainDialog.java	(revision 34317)
@@ -0,0 +1,651 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.imageio.ImageIO;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.JComponent;
+import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
+
+import org.openstreetmap.josm.data.cache.CacheEntry;
+import org.openstreetmap.josm.data.cache.CacheEntryAttributes;
+import org.openstreetmap.josm.data.cache.ICachedLoaderListener;
+import org.openstreetmap.josm.gui.SideButton;
+import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideDataListener;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImportedImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.StreetsidePlugin;
+import org.openstreetmap.josm.plugins.streetside.actions.WalkListener;
+import org.openstreetmap.josm.plugins.streetside.actions.WalkThread;
+import org.openstreetmap.josm.plugins.streetside.cache.StreetsideCache;
+import org.openstreetmap.josm.plugins.streetside.gui.imageinfo.ImageInfoHelpPopup;
+import org.openstreetmap.josm.plugins.streetside.gui.imageinfo.StreetsideViewerHelpPopup;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+ * Toggle dialog that shows an image and some buttons.
+ *
+ * @author nokutu
+ * @author renerr18
+ */
+public final class StreetsideMainDialog extends ToggleDialog implements
+		ICachedLoaderListener, StreetsideDataListener {
+
+	private static final long serialVersionUID = 2645654786827812861L;
+
+	public static final String BASE_TITLE = I18n.marktr("Microsoft Streetside image");
+	private static final String MESSAGE_SEPARATOR = " — ";
+
+	private static StreetsideMainDialog instance;
+
+	private volatile StreetsideAbstractImage image;
+
+	public final SideButton nextButton = new SideButton(new NextPictureAction());
+	public final SideButton previousButton = new SideButton(new PreviousPictureAction());
+	/**
+	 * Button used to jump to the image following the red line
+	 */
+	public final SideButton redButton = new SideButton(new RedAction());
+	/**
+	 * Button used to jump to the image following the blue line
+	 */
+	public final SideButton blueButton = new SideButton(new BlueAction());
+
+	private final SideButton playButton = new SideButton(new PlayAction());
+	private final SideButton pauseButton = new SideButton(new PauseAction());
+	private final SideButton stopButton = new SideButton(new StopAction());
+
+	private ImageInfoHelpPopup imageInfoHelp;
+
+	private StreetsideViewerHelpPopup streetsideViewerHelp;
+
+	/**
+	 * Buttons mode.
+	 *
+	 * @author nokutu
+	 */
+	public enum MODE {
+		/**
+		 * Standard mode to view pictures.
+		 */
+		NORMAL,
+		/**
+		 * Mode when in walk.
+		 */
+		WALK
+	}
+
+	/**
+	 * Object containing the shown image and that handles zoom and drag
+	 */
+	public StreetsideImageDisplay streetsideImageDisplay;
+
+	private StreetsideCache imageCache;
+	public StreetsideCache thumbnailCache;
+
+	private StreetsideMainDialog() {
+		super(I18n.tr(StreetsideMainDialog.BASE_TITLE), "streetside-main", I18n.tr("Open Streetside window"), null, 200,
+				true, StreetsidePreferenceSetting.class);
+		addShortcuts();
+
+		streetsideImageDisplay = new StreetsideImageDisplay();
+
+		blueButton.setForeground(Color.BLUE);
+		redButton.setForeground(Color.RED);
+
+		// TODO: Modes for cubemaps? @rrh
+		setMode(MODE.NORMAL);
+	}
+
+	/**
+	 * Adds the shortcuts to the buttons.
+	 */
+	private void addShortcuts() {
+		nextButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
+				KeyStroke.getKeyStroke("PAGE_DOWN"), "next");
+		nextButton.getActionMap().put("next", new NextPictureAction());
+		previousButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
+				KeyStroke.getKeyStroke("PAGE_UP"), "previous");
+		previousButton.getActionMap().put("previous",
+				new PreviousPictureAction());
+		blueButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
+				KeyStroke.getKeyStroke("control PAGE_UP"), "blue");
+		blueButton.getActionMap().put("blue", new BlueAction());
+		redButton.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
+				KeyStroke.getKeyStroke("control PAGE_DOWN"), "red");
+		redButton.getActionMap().put("red", new RedAction());
+	}
+
+	/**
+	 * Returns the unique instance of the class.
+	 *
+	 * @return The unique instance of the class.
+	 */
+	public static synchronized StreetsideMainDialog getInstance() {
+		if (StreetsideMainDialog.instance == null) {
+			StreetsideMainDialog.instance = new StreetsideMainDialog();
+		}
+		return StreetsideMainDialog.instance;
+	}
+
+	/**
+	 * @return true, iff the singleton instance is present
+	 */
+	public static boolean hasInstance() {
+		return StreetsideMainDialog.instance != null;
+	}
+
+	public synchronized void setImageInfoHelp(ImageInfoHelpPopup popup) {
+		imageInfoHelp = popup;
+	}
+
+	public synchronized void setStreetsideViewerHelp(StreetsideViewerHelpPopup popup) {
+		streetsideViewerHelp = popup;
+	}
+
+	/**
+	 * @return the streetsideViewerHelp
+	 */
+	public StreetsideViewerHelpPopup getStreetsideViewerHelp() {
+		return streetsideViewerHelp;
+	}
+
+	/**
+	 * Sets a new mode for the dialog.
+	 *
+	 * @param mode The mode to be set. Must not be {@code null}.
+	 */
+	public void setMode(MODE mode) {
+		switch (mode) {
+		case WALK:
+			createLayout(
+				streetsideImageDisplay,
+				Arrays.asList(playButton, pauseButton, stopButton)
+			);
+		case NORMAL:
+		default:
+			createLayout(
+		        streetsideImageDisplay,
+		        Arrays.asList(blueButton, previousButton, nextButton, redButton)
+		    );
+		}
+		disableAllButtons();
+		if (MODE.NORMAL.equals(mode)) {
+			updateImage();
+		} 	}
+
+	/**
+	 * Destroys the unique instance of the class.
+	 */
+	public static synchronized void destroyInstance() {
+		StreetsideMainDialog.instance = null;
+	}
+
+	/**
+	 * Downloads the full quality picture of the selected StreetsideImage and sets
+	 * in the StreetsideImageDisplay object.
+	 */
+	public synchronized void updateImage() {
+		updateImage(true);
+	}
+
+	/**
+	 * Downloads the picture of the selected StreetsideImage and sets in the
+	 * StreetsideImageDisplay object.
+	 *
+	 * @param fullQuality If the full quality picture must be downloaded or just the
+	 *                    thumbnail.
+	 */
+	public synchronized void updateImage(boolean fullQuality) {
+		if (!SwingUtilities.isEventDispatchThread()) {
+			SwingUtilities.invokeLater(this::updateImage);
+		} else {
+			if (!StreetsideLayer.hasInstance()) {
+				return;
+			}
+			if (image == null) {
+				streetsideImageDisplay.setImage(null, null);
+				setTitle(I18n.tr(StreetsideMainDialog.BASE_TITLE));
+				disableAllButtons();
+				return;
+			}
+
+			// TODO: help for cubemaps? @rrh
+			if (imageInfoHelp != null && StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.get() > 0 && imageInfoHelp.showPopup()) {
+				// Count down the number of times the popup will be displayed
+				StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.put(StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.get() - 1);
+			}
+
+			// Enables/disables next/previous buttons
+			nextButton.setEnabled(false);
+			previousButton.setEnabled(false);
+			if (image.getSequence() != null) {
+				StreetsideAbstractImage tempImage = image;
+				while (tempImage.next() != null) {
+					tempImage = tempImage.next();
+					if (tempImage.isVisible()) {
+						nextButton.setEnabled(true);
+						break;
+					}
+				}
+			}
+			if (image.getSequence() != null) {
+				StreetsideAbstractImage tempImage = image;
+				while (tempImage.previous() != null) {
+					tempImage = tempImage.previous();
+					if (tempImage.isVisible()) {
+						previousButton.setEnabled(true);
+						break;
+					}
+				}
+			}
+			if (image instanceof StreetsideImage) {
+				final StreetsideImage streetsideImage = (StreetsideImage) image;
+				// Downloads the thumbnail.
+				streetsideImageDisplay.setImage(null, null);
+				if (thumbnailCache != null) {
+					thumbnailCache.cancelOutstandingTasks();
+				}
+				thumbnailCache = new StreetsideCache(streetsideImage.getId(),
+						StreetsideCache.Type.THUMBNAIL);
+				try {
+					thumbnailCache.submit(this, false);
+				} catch (final IOException e) {
+					Logging.error(e);
+				}
+
+				// Downloads the full resolution image.
+				if (fullQuality || new StreetsideCache(streetsideImage.getId(),
+						StreetsideCache.Type.FULL_IMAGE).get() != null) {
+					if (imageCache != null) {
+						imageCache.cancelOutstandingTasks();
+					}
+					imageCache = new StreetsideCache(streetsideImage.getId(),
+							StreetsideCache.Type.FULL_IMAGE);
+					try {
+						imageCache.submit(this, false);
+					} catch (final IOException e) {
+						Logging.error(e);
+					}
+				}
+			// TODO: handle/convert/remove "imported images"
+			} /*else if (image instanceof StreetsideImportedImage) {
+				final StreetsideImportedImage streetsideImage = (StreetsideImportedImage) image;
+				try {
+					streetsideImageDisplay.setImage(streetsideImage.getImage(), null);
+				} catch (final IOException e) {
+					Logging.error(e);
+				}
+			}*/
+			updateTitle();
+		}
+	}
+
+	/**
+	 * Disables all the buttons in the dialog
+	 */
+	public /*private*/ void disableAllButtons() {
+		nextButton.setEnabled(false);
+		previousButton.setEnabled(false);
+		blueButton.setEnabled(false);
+		redButton.setEnabled(false);
+	}
+
+	/**
+	 * Sets a new StreetsideImage to be shown.
+	 *
+	 * @param image The image to be shown.
+	 */
+	public synchronized void setImage(StreetsideAbstractImage image) {
+		this.image = image;
+	}
+
+	/**
+	 * Updates the title of the dialog.
+	 */
+	// TODO: update title for 360 degree viewer? @rrh
+	public synchronized void updateTitle() {
+		if (!SwingUtilities.isEventDispatchThread()) {
+			SwingUtilities.invokeLater(this::updateTitle);
+		} else if (image != null) {
+			final StringBuilder title = new StringBuilder(I18n.tr(StreetsideMainDialog.BASE_TITLE));
+			if (image instanceof StreetsideImage) {
+				final StreetsideImage streetsideImage = (StreetsideImage) image;
+				if (streetsideImage.getCd() != 0) {
+					title.append(StreetsideMainDialog.MESSAGE_SEPARATOR).append(streetsideImage.getDate());
+				}
+				setTitle(title.toString());
+			} else if (image instanceof StreetsideImportedImage) {
+				final StreetsideImportedImage mapillaryImportedImage = (StreetsideImportedImage) image;
+				title.append(StreetsideMainDialog.MESSAGE_SEPARATOR).append(mapillaryImportedImage.getFile().getName());
+				title.append(StreetsideMainDialog.MESSAGE_SEPARATOR).append(mapillaryImportedImage.getDate());
+				setTitle(title.toString());
+			}
+		}
+	}
+
+	/**
+	 * Returns the {@link StreetsideAbstractImage} object which is being shown.
+	 *
+	 * @return The {@link StreetsideAbstractImage} object which is being shown.
+	 */
+	public synchronized StreetsideAbstractImage getImage() {
+		return image;
+	}
+
+	/**
+	 * Action class form the next image button.
+	 *
+	 * @author nokutu
+	 */
+	private static class NextPictureAction extends AbstractAction {
+
+		private static final long serialVersionUID = 6333692154558730392L;
+
+		/**
+		 * Constructs a normal NextPictureAction
+		 */
+		NextPictureAction() {
+			super(I18n.tr("Next picture"));
+			putValue(Action.SHORT_DESCRIPTION, I18n.tr("Shows the next picture in the sequence"));
+			new ImageProvider("help", "next").getResource().attachImageIcon(this, true);
+		}
+
+		@Override
+		public void actionPerformed(ActionEvent e) {
+			StreetsideLayer.getInstance().getData().selectNext();
+		}
+	}
+
+	/**
+	 * Action class for the previous image button.
+	 *
+	 * @author nokutu
+	 */
+	private static class PreviousPictureAction extends AbstractAction {
+
+		private static final long serialVersionUID = 4390593660514657107L;
+
+		/**
+		 * Constructs a normal PreviousPictureAction
+		 */
+		PreviousPictureAction() {
+			super(I18n.tr("Previous picture"));
+			putValue(Action.SHORT_DESCRIPTION, I18n.tr("Shows the previous picture in the sequence"));
+			new ImageProvider("help", "previous").getResource().attachImageIcon(this, true);
+		}
+
+		@Override
+		public void actionPerformed(ActionEvent e) {
+			StreetsideLayer.getInstance().getData().selectPrevious();
+		}
+	}
+
+	/**
+	 * Action class to jump to the image following the red line.
+	 *
+	 * @author nokutu
+	 */
+	private static class RedAction extends AbstractAction {
+
+		private static final long serialVersionUID = -1244456062285831231L;
+
+		/**
+		 * Constructs a normal RedAction
+		 */
+		RedAction() {
+			putValue(Action.NAME, I18n.tr("Jump to red"));
+			putValue(Action.SHORT_DESCRIPTION,
+					I18n.tr("Jumps to the picture at the other side of the red line"));
+			new ImageProvider("dialogs", "red").getResource().attachImageIcon(this, true);
+		}
+
+		// TODO: RedAction for cubemaps? @rrh
+		@Override
+		public void actionPerformed(ActionEvent e) {
+			if (StreetsideMainDialog.getInstance().getImage() != null) {
+				StreetsideLayer.getInstance().getData()
+				.setSelectedImage(StreetsideLayer.getInstance().getNNearestImage(1), true);
+			}
+		}
+	}
+
+	/**
+	 * Action class to jump to the image following the blue line.
+	 *
+	 * @author nokutu
+	 */
+	private static class BlueAction extends AbstractAction {
+
+		private static final long serialVersionUID = 5951233534212838780L;
+
+		/**
+		 * Constructs a normal BlueAction
+		 */
+		BlueAction() {
+			putValue(Action.NAME, I18n.tr("Jump to blue"));
+			putValue(Action.SHORT_DESCRIPTION,
+					I18n.tr("Jumps to the picture at the other side of the blue line"));
+			new ImageProvider("dialogs", "blue").getResource().attachImageIcon(this, true);
+		}
+
+		// TODO: BlueAction for cubemaps?
+		@Override
+		public void actionPerformed(ActionEvent e) {
+			if (StreetsideMainDialog.getInstance().getImage() != null) {
+				StreetsideLayer.getInstance().getData()
+				.setSelectedImage(StreetsideLayer.getInstance().getNNearestImage(2), true);
+			}
+		}
+	}
+
+	private static class StopAction extends AbstractAction implements WalkListener {
+
+		private static final long serialVersionUID = 8789972456611625341L;
+
+		private WalkThread thread;
+
+		/**
+		 * Constructs a normal StopAction
+		 */
+		StopAction() {
+			putValue(Action.NAME, I18n.tr("Stop"));
+			putValue(Action.SHORT_DESCRIPTION, I18n.tr("Stops the walk."));
+			new ImageProvider("dialogs/streetsideStop.png").getResource().attachImageIcon(this, true);
+			StreetsidePlugin.getStreetsideWalkAction().addListener(this);
+		}
+
+		@Override
+		public void actionPerformed(ActionEvent e) {
+			if (thread != null) {
+				thread.stopWalk();
+			}
+		}
+
+		@Override
+		public void walkStarted(WalkThread thread) {
+			this.thread = thread;
+		}
+	}
+
+	private static class PlayAction extends AbstractAction implements WalkListener {
+
+		private static final long serialVersionUID = -1572747020946842769L;
+
+		private transient WalkThread thread;
+
+		/**
+		 * Constructs a normal PlayAction
+		 */
+		PlayAction() {
+			putValue(Action.NAME, I18n.tr("Play"));
+			putValue(Action.SHORT_DESCRIPTION, I18n.tr("Continues with the paused walk."));
+			new ImageProvider("dialogs/streetsidePlay.png").getResource().attachImageIcon(this, true);
+			StreetsidePlugin.getStreetsideWalkAction().addListener(this);
+		}
+
+		@Override
+		public void actionPerformed(ActionEvent e) {
+			if (thread != null) {
+				thread.play();
+			}
+		}
+
+		@Override
+		public void walkStarted(WalkThread thread) {
+			if (thread != null) {
+				this.thread = thread;
+			}
+		}
+	}
+
+	private static class PauseAction extends AbstractAction implements WalkListener {
+
+		/**
+		 *
+		 */
+		private static final long serialVersionUID = -8758326399460817222L;
+		private WalkThread thread;
+
+		/**
+		 * Constructs a normal PauseAction
+		 */
+		PauseAction() {
+			putValue(Action.NAME, I18n.tr("Pause"));
+			putValue(Action.SHORT_DESCRIPTION, I18n.tr("Pauses the walk."));
+			new ImageProvider("dialogs/streetsidePause.png").getResource().attachImageIcon(this, true);
+			StreetsidePlugin.getStreetsideWalkAction().addListener(this);
+		}
+
+		@Override
+		public void actionPerformed(ActionEvent e) {
+			thread.pause();
+		}
+
+		@Override
+		public void walkStarted(WalkThread thread) {
+			this.thread = thread;
+		}
+	}
+
+	/**
+	 * When the pictures are returned from the cache, they are set in the
+	 * {@link StreetsideImageDisplay} object.
+	 */
+	@Override
+	public void loadingFinished(final CacheEntry data, final CacheEntryAttributes attributes, final LoadResult result) {
+		if (!SwingUtilities.isEventDispatchThread()) {
+			SwingUtilities.invokeLater(() -> loadingFinished(data, attributes, result));
+
+		} else if (data != null && result == LoadResult.SUCCESS) {
+			try {
+				final BufferedImage img = ImageIO.read(new ByteArrayInputStream(data.getContent()));
+				if (img == null) {
+					return;
+				}
+				if (
+						streetsideImageDisplay.getImage() == null
+						|| img.getHeight() > streetsideImageDisplay.getImage().getHeight()
+						) {
+					//final StreetsideAbstractImage mai = getImage();
+					streetsideImageDisplay.setImage(
+							img,
+							//mai instanceof StreetsideImage ? ((StreetsideImage) getImage()).getDetections() : null
+							null);
+				}
+			} catch (final IOException e) {
+				Logging.error(e);
+			}
+		}
+	}
+
+
+	/**
+	 * Creates the layout of the dialog.
+	 *
+	 * @param data    The content of the dialog
+	 * @param buttons The buttons where you can click
+	 */
+	public void createLayout(Component data, List<SideButton> buttons) {
+		removeAll();
+		createLayout(data, true, buttons);
+		add(titleBar, BorderLayout.NORTH);
+	}
+
+	@Override
+	public void selectedImageChanged(StreetsideAbstractImage oldImage, StreetsideAbstractImage newImage) {
+		setImage(newImage);
+		updateImage();
+	}
+
+	@Override
+	public void imagesAdded() {
+		// This method is enforced by StreetsideDataListener, but only selectedImageChanged() is needed
+	}
+
+	/**
+	 * @return the streetsideImageDisplay
+	 */
+	public StreetsideImageDisplay getStreetsideImageDisplay() {
+		return streetsideImageDisplay;
+	}
+
+	/**
+	 * @param streetsideImageDisplay the streetsideImageDisplay to set
+	 */
+	public void setStreetsideImageDisplay(StreetsideImageDisplay streetsideImageDisplay) {
+		this.streetsideImageDisplay = streetsideImageDisplay;
+	}
+
+	/**
+	 * @return the streetsideImageDisplay
+	 */
+	/*public StreetsideViewerDisplay getStreetsideViewerDisplay() {
+		return streetsideViewerDisplay;
+	}*/
+
+	/**
+	 * @param streetsideImageDisplay the streetsideImageDisplay to set
+	 */
+	/*public void setStreetsideViewerDisplay(StreetsideViewerDisplay streetsideViewerDisplay) {
+		streetsideViewerDisplay = streetsideViewerDisplay;
+	}*/
+
+	/*private StreetsideViewerDisplay initStreetsideViewerDisplay() {
+		StreetsideViewerDisplay res = new StreetsideViewerDisplay();
+        //this.add(streetsideViewerDisplay);
+
+
+		Platform.runLater(new Runnable() {
+            @Override
+            public void run() {
+            	Scene scene;
+				try {
+					scene = StreetsideViewerDisplay.createScene();
+					res.setScene(scene);
+				} catch (NonInvertibleTransformException e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+            }
+       });
+		return res;
+	}*/
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsidePreferenceSetting.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsidePreferenceSetting.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsidePreferenceSetting.java	(revision 34317)
@@ -0,0 +1,279 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.imageio.ImageIO;
+import javax.swing.AbstractAction;
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSpinner;
+import javax.swing.SpinnerNumberModel;
+import javax.swing.SwingUtilities;
+
+import org.openstreetmap.josm.actions.ExpertToggleAction;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
+import org.openstreetmap.josm.gui.preferences.SubPreferenceSetting;
+import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting;
+import org.openstreetmap.josm.plugins.streetside.StreetsidePlugin;
+import org.openstreetmap.josm.plugins.streetside.gui.boilerplate.StreetsideButton;
+import org.openstreetmap.josm.plugins.streetside.io.download.StreetsideDownloader.DOWNLOAD_MODE;
+import org.openstreetmap.josm.plugins.streetside.oauth.OAuthPortListener;
+import org.openstreetmap.josm.plugins.streetside.oauth.StreetsideLoginListener;
+import org.openstreetmap.josm.plugins.streetside.oauth.StreetsideUser;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideColorScheme;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideUtils;
+import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+ * Creates the preferences panel for the plugin.
+ *
+ * @author nokutu
+ *
+ */
+public class StreetsidePreferenceSetting implements SubPreferenceSetting, StreetsideLoginListener {
+  private final JComboBox<String> downloadModeComboBox = new JComboBox<>(new String[]{
+      DOWNLOAD_MODE.VISIBLE_AREA.getLabel(),
+      DOWNLOAD_MODE.OSM_AREA.getLabel(),
+      DOWNLOAD_MODE.MANUAL_ONLY.getLabel()
+  });
+
+  private final JCheckBox displayHour =
+    // TODO tr( RRH
+    // i18n: Checkbox label in JOSM settings
+    new JCheckBox(I18n.tr("Display hour when the picture was taken"), StreetsideProperties.DISPLAY_HOUR.get());
+  private final JCheckBox format24 =
+    // TODO tr( RRH
+    // i18n: Checkbox label in JOSM settings
+    new JCheckBox(I18n.tr("Use 24 hour format"), StreetsideProperties.TIME_FORMAT_24.get());
+  private final JCheckBox moveTo =
+    // TODO tr( RRH
+    // i18n: Checkbox label in JOSM settings
+    new JCheckBox(I18n.tr("Move to picture''s location with next/previous buttons"), StreetsideProperties.MOVE_TO_IMG.get());
+  private final JCheckBox hoverEnabled =
+    // TODO tr( RRH
+    // i18n: Checkbox label in JOSM settings
+    new JCheckBox(I18n.tr("Preview images when hovering its icon"), StreetsideProperties.HOVER_ENABLED.get());
+  private final JCheckBox cutOffSeq =
+    // TODO tr( RRH
+    // i18n: Checkbox label in JOSM settings
+    new JCheckBox(I18n.tr("Cut off sequences at download bounds"), StreetsideProperties.CUT_OFF_SEQUENCES_AT_BOUNDS.get());
+  private final JCheckBox imageLinkToBlurEditor =
+    new JCheckBox(
+      // TODO tr( RRH
+      // i18n: Checkbox label in JOSM settings
+      I18n.tr("When opening Streetside image in web browser, show the blur editor instead of the image viewer"),
+      StreetsideProperties.IMAGE_LINK_TO_BLUR_EDITOR.get()
+    );
+  private final JCheckBox developer =
+    // TODO tr( RRH
+    // i18n: Checkbox label in JOSM settings
+    new JCheckBox(I18n.tr("Enable experimental beta-features (might be unstable)"), StreetsideProperties.DEVELOPER.get());
+  private final SpinnerNumberModel preFetchSize = new SpinnerNumberModel(
+    StreetsideProperties.PRE_FETCH_IMAGE_COUNT.get().intValue(),
+    0,
+    Integer.MAX_VALUE,
+    1
+  );
+  private final JButton loginButton = new StreetsideButton(new LoginAction(this));
+  private final JButton logoutButton = new StreetsideButton(new LogoutAction());
+  private final JLabel loginLabel = new JLabel();
+  private final JPanel loginPanel = new JPanel();
+
+  @Override
+  public TabPreferenceSetting getTabPreferenceSetting(PreferenceTabbedPane gui) {
+    return gui.getDisplayPreference();
+  }
+
+  @Override
+  public void addGui(PreferenceTabbedPane gui) {
+    JPanel container = new JPanel(new BorderLayout());
+
+    loginPanel.setLayout(new BoxLayout(loginPanel, BoxLayout.LINE_AXIS));
+    loginPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+    loginPanel.setBackground(StreetsideColorScheme.TOOLBAR_DARK_GREY);
+    JLabel brandImage = new JLabel();
+    // TODO: change icons RRH
+    try (InputStream is = StreetsidePreferenceSetting.class.getResourceAsStream("/images/streetside-logo-white.png")) {
+      if (is != null) {
+        brandImage.setIcon(new ImageIcon(ImageIO.read(is)));
+      } else {
+        Logging.warn("Could not load Streetside brand image!");
+      }
+    } catch (IOException e) {
+      Logging.warn("While reading Streetside brand image, an IO-exception occured!");
+    }
+    loginPanel.add(brandImage, 0);
+    loginPanel.add(Box.createHorizontalGlue(), 1);
+    loginLabel.setForeground(Color.WHITE);
+    loginLabel.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
+    loginPanel.add(loginLabel, 2);
+    loginPanel.add(loginButton, 3);
+    onLogout();
+    container.add(loginPanel, BorderLayout.NORTH);
+
+    JPanel mainPanel = new JPanel();
+    mainPanel.setLayout(new GridBagLayout());
+    mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+    downloadModeComboBox.setSelectedItem(DOWNLOAD_MODE.fromPrefId(StreetsideProperties.DOWNLOAD_MODE.get()).getLabel());
+
+    JPanel downloadModePanel = new JPanel();
+    // TODO tr( RRH
+    downloadModePanel.add(new JLabel(I18n.tr("Download mode")));
+    downloadModePanel.add(downloadModeComboBox);
+    mainPanel.add(downloadModePanel, GBC.eol());
+
+    mainPanel.add(displayHour, GBC.eol());
+    mainPanel.add(format24, GBC.eol());
+    mainPanel.add(moveTo, GBC.eol());
+    mainPanel.add(hoverEnabled, GBC.eol());
+    mainPanel.add(cutOffSeq, GBC.eol());
+    mainPanel.add(imageLinkToBlurEditor, GBC.eol());
+
+    final JPanel preFetchPanel = new JPanel();
+    // TODO: tr( RRH
+    // i18n: Spinner label in JOSM settings
+    preFetchPanel.add(new JLabel(I18n.tr("Number of images to be pre-fetched (forwards and backwards)")));
+    final JSpinner spinner = new JSpinner(preFetchSize);
+    final JSpinner.DefaultEditor editor = new JSpinner.NumberEditor(spinner);
+    editor.getTextField().setColumns(3);
+    spinner.setEditor(editor);
+    preFetchPanel.add(spinner);
+    mainPanel.add(preFetchPanel, GBC.eol());
+
+    if (ExpertToggleAction.isExpert() || developer.isSelected()) {
+      mainPanel.add(developer, GBC.eol());
+    }
+    StreetsideColorScheme.styleAsDefaultPanel(
+      mainPanel, downloadModePanel, displayHour, format24, moveTo, hoverEnabled, cutOffSeq, imageLinkToBlurEditor, developer, preFetchPanel
+    );
+    mainPanel.add(Box.createVerticalGlue(), GBC.eol().fill(GridBagConstraints.BOTH));
+
+    container.add(mainPanel, BorderLayout.CENTER);
+
+    synchronized (gui.getDisplayPreference().getTabPane()) {
+      gui.getDisplayPreference().addSubTab(this, "Streetside", new JScrollPane(container));
+      gui.getDisplayPreference().getTabPane().setIconAt(gui.getDisplayPreference().getTabPane().getTabCount()-1, StreetsidePlugin.LOGO.setSize(12, 12).get());
+    }
+
+    new Thread(() -> {
+      String username = StreetsideUser.getUsername();
+      if (username != null) {
+        SwingUtilities.invokeLater(() -> onLogin(StreetsideUser.getUsername()));
+      }
+    }).start();
+  }
+
+  @Override
+  public void onLogin(final String username) {
+    loginPanel.remove(loginButton);
+    loginPanel.add(logoutButton, 3);
+    // TODO tr( RRH
+    loginLabel.setText(I18n.tr("You are logged in as ''{0}''.", username));
+    loginPanel.revalidate();
+    loginPanel.repaint();
+  }
+
+  @Override
+  public void onLogout() {
+    loginPanel.remove(logoutButton);
+    loginPanel.add(loginButton, 3);
+    // TODO: tr( RRH
+    loginLabel.setText(I18n.tr("You are currently not logged in."));
+    loginPanel.revalidate();
+    loginPanel.repaint();
+  }
+
+  @SuppressWarnings("PMD.ShortMethodName")
+  @Override
+  public boolean ok() {
+    StreetsideProperties.DOWNLOAD_MODE.put(DOWNLOAD_MODE.fromLabel(downloadModeComboBox.getSelectedItem().toString()).getPrefId());
+    StreetsideProperties.DISPLAY_HOUR.put(displayHour.isSelected());
+    StreetsideProperties.TIME_FORMAT_24.put(format24.isSelected());
+    StreetsideProperties.MOVE_TO_IMG.put(moveTo.isSelected());
+    StreetsideProperties.HOVER_ENABLED.put(hoverEnabled.isSelected());
+    StreetsideProperties.CUT_OFF_SEQUENCES_AT_BOUNDS.put(cutOffSeq.isSelected());
+    StreetsideProperties.IMAGE_LINK_TO_BLUR_EDITOR.put(imageLinkToBlurEditor.isSelected());
+    StreetsideProperties.DEVELOPER.put(developer.isSelected());
+    StreetsideProperties.PRE_FETCH_IMAGE_COUNT.put(preFetchSize.getNumber().intValue());
+
+    //Restart is never required
+    return false;
+  }
+
+  @Override
+  public boolean isExpert() {
+    return false;
+  }
+
+  /**
+   * Opens the StreetsideOAuthUI window and lets the user log in.
+   *
+   * @author nokutu
+   *
+   */
+  private static class LoginAction extends AbstractAction {
+
+    private static final long serialVersionUID = 8743119160917296506L;
+
+	private final transient StreetsideLoginListener callback;
+
+    LoginAction(StreetsideLoginListener loginCallback) {
+      // TODO tr( RRH
+      super(I18n.tr("Login"));
+      callback = loginCallback;
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent arg0) {
+      OAuthPortListener portListener = new OAuthPortListener(callback);
+      portListener.start();
+      try {
+        // TODO: change URL RRH
+        StreetsideUtils.browse(StreetsideURL.MainWebsite.connect("http://localhost:"+OAuthPortListener.PORT+'/'));
+      } catch (IOException e) {
+        Logging.error(e);
+      }
+    }
+  }
+
+  /**
+   * Logs the user out.
+   *
+   * @author nokutu
+   *
+   */
+  private class LogoutAction extends AbstractAction {
+
+    private static final long serialVersionUID = -4146587895393766981L;
+
+	private LogoutAction() {
+      super(I18n.tr("Logout"));
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent arg0) {
+      StreetsideUser.reset();
+      onLogout();
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideViewerDialog.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideViewerDialog.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideViewerDialog.java	(revision 34317)
@@ -0,0 +1,85 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.util.List;
+
+import org.openstreetmap.josm.gui.SideButton;
+import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
+import org.openstreetmap.josm.plugins.streetside.gui.imageinfo.StreetsideViewerPanel;
+import org.openstreetmap.josm.tools.I18n;
+
+/**
+ * Toggle dialog that shows an image and some buttons.
+ *
+ * @author nokutu
+ */
+
+public final class StreetsideViewerDialog extends ToggleDialog
+		 {
+
+	private static final long serialVersionUID = -8983900297628236197L;
+
+	private static final String BASE_TITLE = I18n.marktr("360° Streetside Viewer");
+
+	private static StreetsideViewerDialog instance;
+
+	/**
+	 * Object containing the shown image and that handles zoom and drag
+	 */
+	private StreetsideViewerPanel streetsideViewerPanel;
+
+	private StreetsideViewerDialog() {
+		super(I18n.tr(StreetsideViewerDialog.BASE_TITLE), "streetside-viewer", I18n.tr("Open Streetside Viewer window"),
+				null, 200, true, StreetsidePreferenceSetting.class);
+		streetsideViewerPanel = new StreetsideViewerPanel();
+		createLayout(streetsideViewerPanel, true, null);
+	}
+
+	/**
+	 * Returns the unique instance of the class.
+	 *
+	 * @return The unique instance of the class.
+	 */
+	public static synchronized StreetsideViewerDialog getInstance() {
+		if (StreetsideViewerDialog.instance == null) {
+			StreetsideViewerDialog.instance = new StreetsideViewerDialog();
+		}
+		return StreetsideViewerDialog.instance;
+	}
+
+	/**
+	 * @return true, iff the singleton instance is present
+	 */
+	public static boolean hasInstance() {
+		return StreetsideViewerDialog.instance != null;
+	}
+
+	/**
+	 * Destroys the unique instance of the class.
+	 */
+	public static synchronized void destroyInstance() {
+		StreetsideViewerDialog.instance = null;
+	}
+
+	/**
+	 * Creates the layout of the dialog.
+	 *
+	 * @param data
+	 *            The content of the dialog
+	 * @param buttons
+	 *            The buttons where you can click
+	 */
+	public void createLayout(Component data, List<SideButton> buttons) {
+		removeAll();
+		createLayout(data, true, buttons);
+		add(titleBar, BorderLayout.NORTH);
+	}
+
+	public StreetsideViewerPanel getStreetsideViewerPanel() {
+		// TODO: check if it's null @rrhs
+		return streetsideViewerPanel;
+	}
+
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideWalkDialog.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideWalkDialog.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/StreetsideWalkDialog.java	(revision 34317)
@@ -0,0 +1,54 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSpinner;
+import javax.swing.SpinnerModel;
+import javax.swing.SpinnerNumberModel;
+
+/**
+ * Dialog to set the walk mode options.
+ *
+ * @author nokutu
+ *
+ */
+public class StreetsideWalkDialog extends JPanel {
+
+  private static final long serialVersionUID = 7974881240732957573L;
+
+  /** Spin containing the interval value. */
+  public SpinnerModel spin;
+  /** Whether it must wait for the picture to be downloaded */
+  public JCheckBox waitForPicture;
+  /** Whether the view must follow the selected image. */
+  public JCheckBox followSelection;
+  /** Go forward or backwards */
+  public JCheckBox goForward;
+
+  /**
+   * Main constructor
+   */
+  public StreetsideWalkDialog() {
+    JPanel interval = new JPanel();
+    spin = new SpinnerNumberModel(2000, 500, 10000, 500);
+    interval.add(new JLabel("Interval (miliseconds): "));
+    interval.add(new JSpinner(spin));
+    add(interval);
+
+    waitForPicture = new JCheckBox(tr("Wait for full quality pictures"));
+    waitForPicture.setSelected(true);
+    add(waitForPicture);
+
+    followSelection = new JCheckBox(tr("Follow selected image"));
+    followSelection.setSelected(true);
+    add(followSelection);
+
+    goForward = new JCheckBox(tr("Go forward"));
+    goForward.setSelected(true);
+    add(goForward);
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/boilerplate/SelectableLabel.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/boilerplate/SelectableLabel.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/boilerplate/SelectableLabel.java	(revision 34317)
@@ -0,0 +1,34 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui.boilerplate;
+
+import java.awt.Color;
+import java.awt.Font;
+
+import javax.swing.JTextPane;
+import javax.swing.UIManager;
+
+public class SelectableLabel extends JTextPane {
+
+  private static final long serialVersionUID = 5432480892000739831L;
+
+  public static final Font DEFAULT_FONT = UIManager.getFont("Label.font").deriveFont(Font.PLAIN);
+  public static final Color DEFAULT_BACKGROUND = UIManager.getColor("Panel.background");
+
+  public SelectableLabel() {
+    super();
+    init();
+  }
+
+  public SelectableLabel(String text) {
+    this();
+    setText(text);
+  }
+
+  private void init() {
+    setEditable(false);
+    setFont(DEFAULT_FONT);
+    setContentType("text/html");
+    setBackground(DEFAULT_BACKGROUND);
+    setBorder(null);
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/boilerplate/StreetsideButton.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/boilerplate/StreetsideButton.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/boilerplate/StreetsideButton.java	(revision 34317)
@@ -0,0 +1,50 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui.boilerplate;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+
+import javax.swing.Action;
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideColorScheme;
+
+
+public class StreetsideButton extends JButton {
+
+  private static final long serialVersionUID = -3060978712233067368L;
+
+  public StreetsideButton(final Action action) {
+    this(action, false);
+  }
+
+  public StreetsideButton(final Action action, boolean slim) {
+    super(action);
+    setForeground(Color.WHITE);
+    setBorder(slim ? BorderFactory.createEmptyBorder(3, 4, 3, 4) : BorderFactory.createEmptyBorder(7, 10, 7, 10));
+  }
+
+  @Override
+  protected void paintComponent(final Graphics g) {
+    if (!isEnabled()) {
+      g.setColor(StreetsideColorScheme.TOOLBAR_DARK_GREY);
+    } else if (getModel().isPressed()) {
+      g.setColor(StreetsideColorScheme.STREETSIDE_BLUE.darker().darker());
+    } else if (getModel().isRollover()) {
+      g.setColor(StreetsideColorScheme.STREETSIDE_BLUE.darker());
+    } else {
+      g.setColor(StreetsideColorScheme.STREETSIDE_BLUE);
+    }
+    ((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+    g.fillRoundRect(0, 0, getWidth(), getHeight(), 3, 3);
+    super.paintComponent(g);
+  }
+
+  @Override
+  public boolean isContentAreaFilled() {
+    return false;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/boilerplate/package-info.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/boilerplate/package-info.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/boilerplate/package-info.java	(revision 34317)
@@ -0,0 +1,5 @@
+// License: GPL. For details, see LICENSE file.
+/**
+ * The GUI components that are special to the mapillary plugin.
+ */
+package org.openstreetmap.josm.plugins.streetside.gui.boilerplate;
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/dialog/ChooseGeoImageLayersDialog.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/dialog/ChooseGeoImageLayersDialog.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/dialog/ChooseGeoImageLayersDialog.java	(revision 34317)
@@ -0,0 +1,134 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui.dialog;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.FlowLayout;
+import java.awt.GraphicsEnvironment;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import javax.swing.AbstractListModel;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.ListCellRenderer;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingConstants;
+import javax.swing.UIManager;
+
+import org.openstreetmap.josm.gui.Notification;
+import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
+import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImportedImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.StreetsidePlugin;
+import org.openstreetmap.josm.plugins.streetside.StreetsideSequence;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.Logging;
+
+public class ChooseGeoImageLayersDialog extends JDialog {
+  private static final long serialVersionUID = -1793622345412435234L;
+  private static final String QUESTION = I18n.marktr("Which image layers do you want to import into the Streetside layer?");
+
+  public ChooseGeoImageLayersDialog(final Component parent, final List<GeoImageLayer> layers) {
+      super(GuiHelper.getFrameForComponent(parent), I18n.tr(QUESTION));
+    final Container c = getContentPane();
+    c.setLayout(new BorderLayout(10, 10));
+
+    final JPanel questionPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 10, 10));
+    questionPanel.add(new JLabel(I18n.tr(QUESTION)));
+    c.add(questionPanel, BorderLayout.NORTH);
+
+    final JList<GeoImageLayer> list = new JList<>();
+    list.setModel(new BasicListModel<>(layers));
+    list.setCellRenderer(new GeoImageLayerListCellRenderer());
+    list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+    c.add(list, BorderLayout.CENTER);
+
+    final JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 10));
+    final JButton cancelButton = new JButton(I18n.tr("Cancel"), new ImageProvider("cancel").get());
+    cancelButton.addActionListener(e -> dispose());
+    cancelButton.requestFocus();
+    buttonPanel.add(cancelButton);
+    final JButton importButton = new JButton(I18n.tr("Import"), new ImageProvider("copy").get());
+    importButton.addActionListener(e -> {
+      list.getSelectedValuesList().parallelStream().map(gil -> {
+        StreetsideSequence seq = new StreetsideSequence();
+        seq.add(
+          gil.getImages().parallelStream()
+            .map(img -> {
+              try {
+                return StreetsideImportedImage.createInstance(img);
+              } catch (IllegalArgumentException iae) {
+                final String message = I18n.tr("Could not import a geotagged image to the Streetside layer!");
+                Logging.log(Logging.LEVEL_WARN, message, iae);
+                if (!GraphicsEnvironment.isHeadless()) {
+                  new Notification(message).setIcon(StreetsidePlugin.LOGO.get()).show();
+                }
+                return null;
+              }
+            })
+            .filter(Objects::nonNull)
+            .sorted((o1, o2) -> (int) Math.signum(o1.getCd() - o2.getCd())) // order by capture date timestamp (ascending)
+            .collect(Collectors.toList())
+        );
+        return seq;
+      }).forEach(seq -> {
+        StreetsideLayer.getInstance().getData().addAll(seq.getImages(), false);
+        // TODO: @rrh
+        //StreetsideImportAction.recordChanges(seq.getImages());
+      });
+      StreetsideLayer.invalidateInstance();
+      dispose();
+    });
+    buttonPanel.add(importButton);
+    c.add(buttonPanel, BorderLayout.SOUTH);
+
+    setModal(true);
+    pack();
+    setLocationRelativeTo(parent);
+  }
+
+  protected static class GeoImageLayerListCellRenderer implements ListCellRenderer<GeoImageLayer> {
+    @Override
+    public Component getListCellRendererComponent(
+      JList<? extends GeoImageLayer> list, GeoImageLayer value, int index, boolean isSelected, boolean cellHasFocus
+    ) {
+      final JLabel result = value == null
+          ? null
+          /* i18n: {0} is the layer name, {1} the number of images in it */
+          : new JLabel(I18n.tr("{0} ({1} images)", value.getName(), value.getImages().size()), value.getIcon(), SwingConstants.LEADING);
+      if (result != null) {
+        result.setOpaque(true);
+        result.setBackground(isSelected ? UIManager.getColor("List.selectionBackground") : UIManager.getColor("List.background"));
+      }
+      return result;
+    }
+  }
+
+  private static class BasicListModel<T> extends AbstractListModel<T> {
+    private static final long serialVersionUID = 3107247955341855290L;
+    private final List<T> list;
+
+    public BasicListModel(List<T> list) {
+      this.list = list == null ? new ArrayList<>() : list;
+    }
+
+    @Override
+    public int getSize() {
+      return list.size();
+    }
+
+    @Override
+    public T getElementAt(int index) {
+      return list.get(index);
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/AddTagToPrimitiveAction.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/AddTagToPrimitiveAction.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/AddTagToPrimitiveAction.java	(revision 34317)
@@ -0,0 +1,67 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui.imageinfo;
+
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.AbstractPrimitive;
+import org.openstreetmap.josm.data.osm.Tag;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
+
+public class AddTagToPrimitiveAction extends AbstractAction {
+
+  private static final long serialVersionUID = -2134831346322019333L;
+
+  private Tag tag;
+  private AbstractPrimitive target;
+
+  public AddTagToPrimitiveAction(final String name) {
+    super(name, ImageProvider.get("dialogs/add", ImageSizes.SMALLICON));
+  }
+
+  public void setTag(Tag tag) {
+    this.tag = tag;
+    updateEnabled();
+  }
+
+  public void setTarget(AbstractPrimitive target) {
+    this.target = target;
+    updateEnabled();
+  }
+
+  private void updateEnabled() {
+    setEnabled(tag != null && target != null);
+  }
+
+  @Override
+  public void actionPerformed(ActionEvent e) {
+    if (target != null && tag != null) {
+      int conflictResolution = JOptionPane.YES_OPTION;
+      if (target.hasKey(tag.getKey()) && !target.hasTag(tag.getKey(), tag.getValue())) {
+        conflictResolution = JOptionPane.showConfirmDialog(
+          Main.parent,
+          "<html>" +
+            // TODO: tr( RRH
+            I18n.tr("A tag with key <i>{0}</i> is already present on the selected OSM object.", tag.getKey()) + "<br>" +
+            I18n.tr(
+              "Do you really want to replace the current value <i>{0}</i> with the new value <i>{1}</i>?",
+              target.get(tag.getKey()),
+              tag.getValue()
+            ) + "</html>",
+          I18n.tr("Tag conflict"),
+          JOptionPane.YES_NO_OPTION,
+          JOptionPane.WARNING_MESSAGE
+        );
+      }
+      if (JOptionPane.YES_OPTION == conflictResolution) {
+        target.put(tag);
+        target.setModified(true);
+      }
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ClipboardAction.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ClipboardAction.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ClipboardAction.java	(revision 34317)
@@ -0,0 +1,103 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui.imageinfo;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Transferable;
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.BorderFactory;
+import javax.swing.JLabel;
+import javax.swing.JPopupMenu;
+
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
+
+public class ClipboardAction extends AbstractAction {
+
+  private static final long serialVersionUID = -7298944557860158010L;
+  /**
+   * The duration in milliseconds for which the popup will be shown
+   */
+  private static final long POPUP_DURATION = 3000;
+  /**
+   * A small popup that shows up when the key has been moved to the clipboard
+   */
+  private final JPopupMenu popup;
+  /**
+   * The component which is used as parent of the shown popup.
+   * If this is <code>null</code>, no popup will be shown.
+   */
+  private Component popupParent;
+  /**
+   * The UNIX epoch time when the popup for this action was shown the last time
+   */
+  private long lastPopupShowTime;
+  /**
+   * The contents that are transfered into the clipboard when the action is executed.
+   * If this is <code>null</code>, the clipboard won't be changed.
+   */
+  private Transferable contents;
+
+  public ClipboardAction(final String name, final Transferable contents) {
+    super(name, ImageProvider.get("copy", ImageSizes.SMALLICON));
+    this.contents = contents;
+
+    // Init popup
+    popup = new JPopupMenu();
+    // TODO: tr( RRH
+    JLabel label = new JLabel(I18n.tr("Key copied to clipboard") + '…');
+    label.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+    popup.add(label);
+    popup.setBackground(new Color(0f, 0f, 0f, .5f));
+    label.setForeground(Color.WHITE);
+  }
+
+  /**
+   * @param contents the contents, which should be copied to the clipboard when the {@link Action} is executed
+   */
+  public void setContents(Transferable contents) {
+    this.contents = contents;
+    setEnabled(contents != null);
+  }
+
+  /**
+   * Sets the component, under which the popup will be shown, which indicates that the key was copied to the clipboard.
+   * @param popupParent the component to set as parent of the popup
+   */
+  public void setPopupParent(Component popupParent) {
+    this.popupParent = popupParent;
+  }
+
+  /* (non-Javadoc)
+   * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+   */
+  @Override
+  public void actionPerformed(ActionEvent e) {
+    if (contents != null) {
+      Toolkit.getDefaultToolkit().getSystemClipboard().setContents(contents, null);
+      if (popupParent != null) {
+        popup.show(popupParent, 0, popupParent.getHeight() + 2);
+        new Thread(() -> {
+          long threadStart = System.currentTimeMillis();
+          lastPopupShowTime = threadStart;
+          try {
+            Thread.sleep(POPUP_DURATION);
+          } catch (InterruptedException e1) {
+            if (threadStart == lastPopupShowTime) {
+              popup.setVisible(false);
+            }
+          }
+          if (System.currentTimeMillis() >= lastPopupShowTime + POPUP_DURATION) {
+            popup.setVisible(false);
+          }
+        }).start();
+      }
+    }
+  }
+
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ImageInfoHelpPopup.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ImageInfoHelpPopup.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ImageInfoHelpPopup.java	(revision 34317)
@@ -0,0 +1,92 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui.imageinfo;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.IllegalComponentStateException;
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JTextPane;
+
+import org.openstreetmap.josm.plugins.streetside.gui.boilerplate.SelectableLabel;
+import org.openstreetmap.josm.plugins.streetside.gui.boilerplate.StreetsideButton;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideColorScheme;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.Logging;
+
+public class ImageInfoHelpPopup extends JPopupMenu {
+
+  private static final long serialVersionUID = -1721594904273820586L;
+
+  private final Component invokerComp;
+  private boolean alreadyDisplayed;
+
+  public ImageInfoHelpPopup(Component invoker) {
+    invokerComp = invoker;
+    removeAll();
+    setLayout(new BorderLayout());
+
+    JPanel topBar = new JPanel();
+    topBar.add(new JLabel(ImageProvider.get("streetside-logo-white")));
+    topBar.setBackground(StreetsideColorScheme.TOOLBAR_DARK_GREY);
+    add(topBar, BorderLayout.NORTH);
+
+    JTextPane mainText = new JTextPane();
+    mainText.setContentType("text/html");
+    mainText.setFont(SelectableLabel.DEFAULT_FONT);
+    // TODO: tr( RRH
+    mainText.setText(
+      "<html><div style='width:250px'>" +
+      I18n.tr("The Streetside plugin now uses a separate panel to display extra information (like the image key) and actions for the currently selected Streetside image (like viewing it in a browser).") +
+      "<br><br>" +
+      I18n.tr("It can be activated by clicking the left button at the bottom of this message or the button in the toolbar on the left, which uses the same icon.") +
+      "</div></html>"
+    );
+    add(mainText, BorderLayout.CENTER);
+
+    JPanel bottomBar = new JPanel();
+    bottomBar.setBackground(new Color(0x00FFFFFF, true));
+    StreetsideButton infoButton = new StreetsideButton(ImageInfoPanel.getInstance().getToggleAction());
+    infoButton.addActionListener(e -> setVisible(false));
+    bottomBar.add(infoButton);
+		StreetsideButton closeBtn = new StreetsideButton(new AbstractAction() {
+
+			private static final long serialVersionUID = 2853315308169651854L;
+
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				setVisible(false);
+				StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.put(0);
+			}
+		});
+
+		closeBtn.setText(I18n.tr("I got it, close this."));
+		bottomBar.add(closeBtn);
+		add(bottomBar, BorderLayout.SOUTH);
+
+		setBackground(Color.WHITE);
+	}
+
+  /**
+   * @return <code>true</code> if the popup is displayed
+   */
+  public boolean showPopup() {
+    if (!alreadyDisplayed && invokerComp.isShowing()) {
+      try {
+        show(invokerComp, invokerComp.getWidth(), 0);
+        alreadyDisplayed = true;
+        return true;
+      } catch (IllegalComponentStateException e) {
+        Logging.log(Logging.LEVEL_WARN, "Could not show ImageInfoHelpPopup, because probably the invoker component has disappeared from screen.", e);
+      }
+    }
+    return false;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ImageInfoPanel.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ImageInfoPanel.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ImageInfoPanel.java	(revision 34317)
@@ -0,0 +1,238 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui.imageinfo;
+
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Image;
+import java.awt.Insets;
+import java.awt.datatransfer.StringSelection;
+import java.awt.image.BufferedImage;
+import java.util.Collection;
+
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextPane;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.openstreetmap.josm.data.SelectionChangedListener;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Tag;
+import org.openstreetmap.josm.data.preferences.AbstractProperty.ValueChangeListener;
+import org.openstreetmap.josm.gui.dialogs.ToggleDialog;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideDataListener;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.gui.boilerplate.SelectableLabel;
+import org.openstreetmap.josm.plugins.streetside.gui.boilerplate.StreetsideButton;
+import org.openstreetmap.josm.plugins.streetside.model.UserProfile;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL;
+import org.openstreetmap.josm.tools.I18n;
+
+public final class ImageInfoPanel extends ToggleDialog implements StreetsideDataListener, SelectionChangedListener {
+  private static final long serialVersionUID = 4141847503072417190L;
+  private static final Log L = LogFactory.getLog(ImageInfoPanel.class);
+  private static ImageInfoPanel instance;
+  private static final ImageIcon EMPTY_USER_AVATAR = new ImageIcon(new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB));
+
+  //private final JLabel numDetectionsLabel;
+  //private final JCheckBox showDetectionsCheck;
+  private final JLabel usernameLabel;
+  private final JTextPane imgKeyValue;
+  private final WebLinkAction imgLinkAction;
+  private final ClipboardAction copyImgKeyAction;
+  private final AddTagToPrimitiveAction addStreetsideTagAction;
+  private final JTextPane seqKeyValue;
+
+  private ValueChangeListener<Boolean> imageLinkChangeListener;
+
+  private ImageInfoPanel() {
+    super(
+      I18n.tr("Streetside Image info"),
+      "streetside-info",
+      I18n.tr("Displays detail information on the currently selected Streetside image"),
+      null,
+      150
+    );
+    DataSet.addSelectionListener(this);
+
+    //numDetectionsLabel = new JLabel();
+    //numDetectionsLabel.setFont(numDetectionsLabel.getFont().deriveFont(Font.PLAIN));
+
+    //showDetectionsCheck = new JCheckBox(I18n.tr("Show detections on top of image"));
+    //showDetectionsCheck.setSelected(StreetsideProperties.SHOW_DETECTED_SIGNS.get());
+    /*showDetectionsCheck.addActionListener(
+      action -> StreetsideProperties.SHOW_DETECTED_SIGNS.put(showDetectionsCheck.isSelected())
+    );
+    StreetsideProperties.SHOW_DETECTED_SIGNS.addListener(
+      valueChange -> showDetectionsCheck.setSelected(StreetsideProperties.SHOW_DETECTED_SIGNS.get())
+    );*/
+
+    usernameLabel = new JLabel();
+    usernameLabel.setFont(usernameLabel.getFont().deriveFont(Font.PLAIN));
+
+    imgKeyValue = new SelectableLabel();
+
+    imgLinkAction = new WebLinkAction(I18n.tr("View in browser"), null);
+
+    copyImgKeyAction = new ClipboardAction(I18n.tr("Copy key"), null);
+    StreetsideButton copyButton = new StreetsideButton(copyImgKeyAction, true);
+    copyImgKeyAction.setPopupParent(copyButton);
+
+    addStreetsideTagAction = new AddTagToPrimitiveAction(I18n.tr("Add Streetside tag"));
+
+    JPanel imgKey = new JPanel();
+    imgKey.add(imgKeyValue);
+    imgKey.add(copyButton);
+    JPanel imgButtons = new JPanel();
+    imgButtons.add(new StreetsideButton(imgLinkAction, true));
+    imgButtons.add(new StreetsideButton(addStreetsideTagAction, true));
+    seqKeyValue = new SelectableLabel();
+
+    JPanel root = new JPanel(new GridBagLayout());
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.insets = new Insets(0, 5, 0, 5);
+
+    // Left column
+    gbc.gridx = 0;
+    gbc.gridy = 0;
+    gbc.anchor = GridBagConstraints.LINE_END;
+    gbc.gridwidth = 1;
+    gbc.gridheight = 2;
+    root.add(new JLabel(I18n.tr("Image detections")), gbc);
+    gbc.gridy += 2;
+    gbc.gridheight = 1;
+    root.add(new JLabel(I18n.tr("User")), gbc);
+    gbc.gridy++;
+    root.add(new JLabel(I18n.tr("Image actions")), gbc);
+    gbc.gridy++;
+    root.add(new JLabel(I18n.tr("Image key")), gbc);
+    gbc.gridy++;
+    root.add(new JLabel(I18n.tr("Sequence key")), gbc);
+
+    // Right column
+    gbc.weightx = 1;
+    gbc.gridx++;
+    gbc.gridy = 0;
+    gbc.anchor = GridBagConstraints.LINE_START;
+    //root.add(numDetectionsLabel, gbc);
+    //gbc.gridy++;
+    //root.add(showDetectionsCheck, gbc);
+    //gbc.gridy++;
+    root.add(usernameLabel, gbc);
+    gbc.gridy++;
+    root.add(imgButtons, gbc);
+    gbc.gridy++;
+    root.add(imgKey, gbc);
+    gbc.gridy++;
+    root.add(seqKeyValue, gbc);
+
+    createLayout(root, true, null);
+    selectedImageChanged(null, null);
+  }
+
+  public static ImageInfoPanel getInstance() {
+    synchronized (ImageInfoPanel.class) {
+      if (instance == null) {
+        instance = new ImageInfoPanel();
+      }
+      return instance;
+    }
+  }
+
+  /**
+   * Destroys the unique instance of the class.
+   */
+  public static synchronized void destroyInstance() {
+    instance = null;
+  }
+
+  /* (non-Javadoc)
+   * @see org.openstreetmap.josm.gui.dialogs.ToggleDialog#stateChanged()
+   */
+  @Override
+  protected void stateChanged() {
+    super.stateChanged();
+    if (isDialogShowing()) { // If the user opens the dialog once, no longer show the help message
+      StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.put(0);
+    }
+  }
+
+  /* (non-Javadoc)
+   * @see org.openstreetmap.josm.plugins.streetside.StreetsideDataListener#imagesAdded()
+   */
+  @Override
+  public void imagesAdded() {
+    // Method is not needed, but enforcesd by the interface StreetsideDataListener
+  }
+
+  /* (non-Javadoc)
+   * @see org.openstreetmap.josm.plugins.streetside.StreetsideDataListener#selectedImageChanged(org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage, org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage)
+   */
+  @Override
+  public synchronized void selectedImageChanged(final StreetsideAbstractImage oldImage, final StreetsideAbstractImage newImage) {
+    L.debug(String.format(
+      "Selected Streetside image changed from %s to %s.",
+      oldImage instanceof StreetsideImage ? ((StreetsideImage) oldImage).getId() : "‹none›",
+      newImage instanceof StreetsideImage ? ((StreetsideImage) newImage).getId() : "‹none›"
+    ));
+
+    //numDetectionsLabel.setText(I18n.tr("{0} detections", newImage instanceof StreetsideImage ? ((StreetsideImage) newImage).getDetections().size() : 0));
+    imgKeyValue.setEnabled(newImage instanceof StreetsideImage);
+    final String newImageKey = newImage instanceof StreetsideImage ? ((StreetsideImage) newImage).getId(): null;
+    if (newImageKey != null) {
+      imageLinkChangeListener = b -> imgLinkAction.setURL(
+        StreetsideProperties.IMAGE_LINK_TO_BLUR_EDITOR.get()
+        ? StreetsideURL.MainWebsite.blurEditImage(newImageKey)
+        : StreetsideURL.MainWebsite.browseImage(newImageKey)
+      );
+      imageLinkChangeListener.valueChanged(null);
+      StreetsideProperties.IMAGE_LINK_TO_BLUR_EDITOR.addListener(imageLinkChangeListener);
+
+      imgKeyValue.setText(newImageKey);
+      copyImgKeyAction.setContents(new StringSelection(newImageKey));
+      addStreetsideTagAction.setTag(new Tag("streetside", newImageKey));
+    } else {
+      if (imageLinkChangeListener != null) {
+        StreetsideProperties.IMAGE_LINK_TO_BLUR_EDITOR.removeListener(imageLinkChangeListener);
+        imageLinkChangeListener = null;
+      }
+      imgLinkAction.setURL(null);
+
+      imgKeyValue.setText('‹' + I18n.tr("image has no key") + '›');
+      copyImgKeyAction.setContents(null);
+      addStreetsideTagAction.setTag(null);
+    }
+
+    final UserProfile user = newImage instanceof StreetsideImage ? ((StreetsideImage) newImage).getUser() : null;
+    usernameLabel.setEnabled(user != null);
+    if (user != null) {
+      usernameLabel.setText(user.getUsername());
+      usernameLabel.setIcon(new ImageIcon(user.getAvatar().getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH)));
+    } else {
+      usernameLabel.setText("‹" + I18n.tr("unknown user") + "›");
+      usernameLabel.setIcon(EMPTY_USER_AVATAR);
+    }
+
+    final boolean partOfSequence = newImage != null && newImage.getSequence() != null && newImage.getSequence().getId() != null;
+    seqKeyValue.setEnabled(partOfSequence);
+    if (partOfSequence) {
+      seqKeyValue.setText(newImage.getSequence().getId());
+    } else {
+      seqKeyValue.setText('‹' + I18n.tr("sequence has no id") + '›');
+    }
+  }
+
+  /* (non-Javadoc)
+   * @see org.openstreetmap.josm.data.SelectionChangedListener#selectionChanged(java.util.Collection)
+   */
+  @Override
+  public synchronized void selectionChanged(final Collection<? extends OsmPrimitive> sel) {
+    L.debug(String.format("Selection changed. %d primitives are selected.", sel == null ? 0 : sel.size()));
+    addStreetsideTagAction.setTarget(sel != null && sel.size() == 1 ? sel.iterator().next() : null);
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/StreetsideViewerHelpPopup.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/StreetsideViewerHelpPopup.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/StreetsideViewerHelpPopup.java	(revision 34317)
@@ -0,0 +1,90 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui.imageinfo;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.IllegalComponentStateException;
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JTextPane;
+
+import org.openstreetmap.josm.plugins.streetside.gui.boilerplate.SelectableLabel;
+import org.openstreetmap.josm.plugins.streetside.gui.boilerplate.StreetsideButton;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideColorScheme;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.Logging;
+
+public class StreetsideViewerHelpPopup extends JPopupMenu {
+
+	private static final long serialVersionUID = -7840242522398163839L;
+
+	private final Component invokerComp;
+	private boolean alreadyDisplayed;
+
+	public StreetsideViewerHelpPopup(Component invoker) {
+
+		invokerComp = invoker;
+		removeAll();
+		setLayout(new BorderLayout());
+
+		JPanel topBar = new JPanel();
+		topBar.add(new JLabel(ImageProvider.get("streetside-logo-white")));
+		topBar.setBackground(StreetsideColorScheme.TOOLBAR_DARK_GREY);
+		add(topBar, BorderLayout.NORTH);
+
+		JTextPane mainText = new JTextPane();
+		mainText.setContentType("text/html");
+		mainText.setFont(SelectableLabel.DEFAULT_FONT);
+		mainText.setText("<html><div style='width:250px'>" + I18n.tr(
+				"The Streetside plugin now uses a separate panel to display extra information (like the image key) and actions for the currently selected Streetside image (like viewing it in a browser).")
+				+ "<br><br>"
+				+ I18n.tr(
+						"It can be activated by clicking the left button at the bottom of this message or the button in the toolbar on the left, which uses the same icon.")
+				+ "</div></html>");
+		add(mainText, BorderLayout.CENTER);
+
+		JPanel bottomBar = new JPanel();
+		bottomBar.setBackground(new Color(0x00FFFFFF, true));
+		StreetsideButton infoButton = new StreetsideButton(ImageInfoPanel.getInstance().getToggleAction());
+		infoButton.addActionListener(e -> setVisible(false));
+		bottomBar.add(infoButton);
+		StreetsideButton closeBtn = new StreetsideButton(new AbstractAction() {
+			private static final long serialVersionUID = -6193886964751195196L;
+
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				setVisible(false);
+				StreetsideProperties.IMAGEINFO_HELP_COUNTDOWN.put(0);
+			}
+		});
+
+		closeBtn.setText(I18n.tr("I got it, close this."));
+ bottomBar.add(closeBtn);
+ add(bottomBar, BorderLayout.SOUTH);
+
+ setBackground(Color.WHITE);
+}
+
+/**
+* @return <code>true</code> if the popup is displayed
+*/
+public boolean showPopup() {
+ if (!alreadyDisplayed && invokerComp.isShowing()) {
+   try {
+     show(invokerComp, invokerComp.getWidth(), 0);
+     alreadyDisplayed = true;
+     return true;
+   } catch (IllegalComponentStateException e) {
+     Logging.log(Logging.LEVEL_WARN, "Could not show ImageInfoHelpPopup, because probably the invoker component has disappeared from screen.", e);
+   }
+ }
+ return false;
+}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/StreetsideViewerPanel.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/StreetsideViewerPanel.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/StreetsideViewerPanel.java	(revision 34317)
@@ -0,0 +1,174 @@
+//License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui.imageinfo;
+
+import java.awt.BorderLayout;
+import java.util.Collection;
+
+import javax.swing.JCheckBox;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+import org.openstreetmap.josm.data.SelectionChangedListener;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.preferences.AbstractProperty.ValueChangeListener;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideDataListener;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.actions.ImageReloadAction;
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
+import org.openstreetmap.josm.plugins.streetside.cubemap.GraphicsUtils;
+import org.openstreetmap.josm.plugins.streetside.gui.boilerplate.StreetsideButton;
+import org.openstreetmap.josm.plugins.streetside.utils.CubemapBox;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.Logging;
+
+
+public final class StreetsideViewerPanel extends JPanel
+		implements StreetsideDataListener, SelectionChangedListener {
+
+	private static final long serialVersionUID = 4141847503072417190L;
+
+	private JCheckBox highResImageryCheck;
+	private WebLinkAction imgLinkAction;
+	private ImageReloadAction imgReloadAction;
+	private ValueChangeListener<Boolean> imageLinkChangeListener;
+
+	private static ThreeSixtyDegreeViewerPanel threeSixtyDegreeViewerPanel;
+
+	public StreetsideViewerPanel() {
+
+		super(new BorderLayout());
+
+		SwingUtilities.invokeLater(new Runnable() {
+		     @Override
+		     public void run() {
+		    	 initializeAndStartGUI();
+		     }
+		 });
+
+		selectedImageChanged(null, null);
+
+		setToolTipText(I18n.tr("Select Microsoft Streetside from the Imagery menu, then click on a blue vector bubble.."));
+	}
+
+	private void initializeAndStartGUI() {
+
+		DataSet.addSelectionListener(this);
+
+		threeSixtyDegreeViewerPanel = new ThreeSixtyDegreeViewerPanel();
+
+		GraphicsUtils.PlatformHelper.run(() -> {
+	    	threeSixtyDegreeViewerPanel.initialize();
+		});
+
+		add(threeSixtyDegreeViewerPanel, BorderLayout.CENTER);
+		revalidate();
+		repaint();
+	    JPanel checkPanel = new JPanel();
+
+	    imgReloadAction = new ImageReloadAction(I18n.tr("Reload"));
+
+	    StreetsideButton imgReloadButton = new StreetsideButton(imgReloadAction);
+		highResImageryCheck = new JCheckBox(I18n.tr("High resolution"));
+	    highResImageryCheck.setSelected(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get());
+	    highResImageryCheck.addActionListener(
+	      action -> StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.put(highResImageryCheck.isSelected())
+	    );
+	    StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.addListener(
+	      valueChange -> highResImageryCheck.setSelected(StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get())
+	    );
+	    checkPanel.add(highResImageryCheck, BorderLayout.WEST);
+	    checkPanel.add(imgReloadButton, BorderLayout.EAST);
+
+	    JPanel privacyLink = new JPanel();
+
+	    imgLinkAction = new WebLinkAction(I18n.tr("Report a privacy concern with this image"), null);
+	    privacyLink.add(new StreetsideButton(imgLinkAction, true));
+	    checkPanel.add(privacyLink, BorderLayout.PAGE_END);
+
+	    add(checkPanel, BorderLayout.PAGE_START);
+	    add(threeSixtyDegreeViewerPanel, BorderLayout.CENTER);
+
+	    add(privacyLink, BorderLayout.PAGE_END);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see
+	 * org.openstreetmap.josm.plugins.streetside.StreetsideDataListener#imagesAdded(
+	 * )
+	 */
+	@Override
+	public void imagesAdded() {
+		// Method is not needed, but enforcesd by the interface StreetsideDataListener
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see org.openstreetmap.josm.plugins.streetside.StreetsideDataListener#
+	 * selectedImageChanged(org.openstreetmap.josm.plugins.streetside.
+	 * StreetsideAbstractImage,
+	 * org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage)
+	 */
+	@Override
+	public synchronized void selectedImageChanged(final StreetsideAbstractImage oldImage,
+			final StreetsideAbstractImage newImage) {
+
+		// method is invoked with null initially by framework
+		if(newImage!=null) {
+
+		    Logging.debug(String.format(
+		      "Selected Streetside image changed from %s to %s.",
+		      oldImage instanceof StreetsideImage ? ((StreetsideImage) oldImage).getId() : "‹none›",
+		      newImage instanceof StreetsideImage ? ((StreetsideImage) newImage).getId() : "‹none›"
+		    ));
+
+		    //imgIdValue.setEnabled(newImage instanceof StreetsideImage);
+		    final String newImageId = newImage instanceof StreetsideImage ? ((StreetsideImage) newImage).getId(): null;
+		    if (newImageId != null) {
+		      final String bubbleId = CubemapUtils.convertQuaternary2Decimal(newImageId);
+		      imageLinkChangeListener = b -> imgLinkAction.setURL(
+		        StreetsideURL.MainWebsite.streetsidePrivacyLink(bubbleId)
+		      );
+		      imageLinkChangeListener.valueChanged(null);
+		      StreetsideProperties.CUBEMAP_LINK_TO_BLUR_EDITOR.addListener(imageLinkChangeListener);
+
+
+		    } else {
+		      if (imageLinkChangeListener != null) {
+		        StreetsideProperties.CUBEMAP_LINK_TO_BLUR_EDITOR.removeListener(imageLinkChangeListener);
+		        imageLinkChangeListener = null;
+		      }
+		      imgLinkAction.setURL(null);
+		    }
+		  }
+	}
+
+	/*
+	 * (non-Javadoc)
+	 *
+	 * @see
+	 * org.openstreetmap.josm.data.SelectionChangedListener#selectionChanged(java.
+	 * util.Collection)
+	 */
+	@Override
+	public synchronized void selectionChanged(final Collection<? extends OsmPrimitive> sel) {
+		Logging.debug(String.format("Selection changed. %d primitives are selected.", sel == null ? 0 : sel.size()));
+	}
+
+	public CubemapBox getCubemapBox() {
+		return threeSixtyDegreeViewerPanel.getCubemapBox();
+	}
+
+	/**
+	 * @return the threeSixtyDegreeViewerPanel
+	 */
+	public static ThreeSixtyDegreeViewerPanel getThreeSixtyDegreeViewerPanel() {
+		return threeSixtyDegreeViewerPanel;
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ThreeSixtyDegreeViewerPanel.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ThreeSixtyDegreeViewerPanel.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/ThreeSixtyDegreeViewerPanel.java	(revision 34317)
@@ -0,0 +1,383 @@
+//License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui.imageinfo;
+
+import java.awt.image.BufferedImage;
+
+import org.openstreetmap.josm.plugins.streetside.cubemap.CameraTransformer;
+import org.openstreetmap.josm.plugins.streetside.cubemap.GraphicsUtils;
+import org.openstreetmap.josm.plugins.streetside.utils.CubemapBox;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.Logging;
+
+import javafx.application.Platform;
+import javafx.embed.swing.JFXPanel;
+import javafx.scene.Group;
+import javafx.scene.PerspectiveCamera;
+import javafx.scene.PointLight;
+import javafx.scene.Scene;
+import javafx.scene.SceneAntialiasing;
+import javafx.scene.control.TextArea;
+import javafx.scene.image.Image;
+import javafx.scene.input.KeyCode;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.VBox;
+import javafx.scene.paint.Color;
+import javafx.scene.transform.NonInvertibleTransformException;
+
+
+@SuppressWarnings("restriction")
+public class ThreeSixtyDegreeViewerPanel extends JFXPanel {
+
+	private static final long serialVersionUID = -4940350009018422000L;
+
+	private static Group root;
+	private static Group subGroup;
+	private static CubemapBox cubemapBox;
+	private static PerspectiveCamera camera;
+	private static CameraTransformer cameraTransform = new CameraTransformer();
+
+	private static double mousePosX;
+	private static double mousePosY;
+	private static double mouseOldX;
+	private static double mouseOldY;
+	private static double mouseDeltaX;
+	private static double mouseDeltaY;
+	private static double cameraDistance = 5000;
+
+	// Supply Image Paths or a NullPointer will occur
+	private static Image front;
+	private static Image right;
+	private static Image back;
+	private static Image left;
+	private static Image up;
+	private static Image down;
+
+	public ThreeSixtyDegreeViewerPanel() {
+		// constructor
+	}
+
+	void initialize() {
+
+		root = new Group();
+
+		camera = new PerspectiveCamera(true);
+		cameraTransform.setTranslate(0, 0, 0);
+		cameraTransform.getChildren().addAll(camera);
+		camera.setNearClip(0.1);
+		camera.setFarClip(1000000.0);
+		camera.setFieldOfView(42);
+		camera.setTranslateZ(-cameraDistance);
+		// cameraTransform.ry.setAngle(-45.0);
+		// cameraTransform.rx.setAngle(-10.0);
+		// add a Point Light for better viewing of the grid coordinate system
+		final PointLight light = new PointLight(Color.WHITE);
+
+		cameraTransform.getChildren().add(light);
+		light.setTranslateX(camera.getTranslateX());
+		light.setTranslateY(camera.getTranslateY());
+		light.setTranslateZ(camera.getTranslateZ());
+
+		root.getChildren().add(cameraTransform);
+
+		final double size = 100000D;
+
+		cubemapBox = new CubemapBox(front, right, back, left, up, down, size, camera);
+
+		subGroup = new Group();
+		subGroup.getChildren().add(cameraTransform);
+
+		Platform.runLater(new Runnable() {
+			@Override
+			public void run() {
+				try {
+					// TODO: create Default Scene and replace with 360 degree scene @rrh
+					setScene(createScene());
+				} catch (NonInvertibleTransformException e) {
+					Logging.error(I18n.tr("Error initializing StreetsideViewerPanel - JavaFX {0}", e.getMessage()));
+				}
+			}
+		});
+	}
+
+	private static Scene createScene() throws NonInvertibleTransformException {
+
+		/*root = new Group();
+
+		camera = new PerspectiveCamera(true);
+		cameraTransform.setTranslate(0, 0, 0);
+		cameraTransform.getChildren().addAll(camera);
+		camera.setNearClip(0.1);
+		camera.setFarClip(1000000.0);
+		camera.setFieldOfView(42);
+		camera.setTranslateZ(-cameraDistance);
+		final PointLight light = new PointLight(Color.WHITE);
+
+		cameraTransform.getChildren().add(light);
+		light.setTranslateX(camera.getTranslateX());
+		light.setTranslateY(camera.getTranslateY());
+		light.setTranslateZ(camera.getTranslateZ());
+
+		root.getChildren().add(cameraTransform);
+
+		// Load Cubemap box AFTER camera is initialized
+		final double size = 100000D;
+
+		cubemapBox = new CubemapBox(null, null, null, null, null, null, size, camera);
+
+		subGroup = new Group();
+		subGroup.getChildren().add(cameraTransform);*/
+
+		final Scene scene = new Scene(new Group(root), 1024, 668, true, SceneAntialiasing.BALANCED);
+		scene.setFill(Color.TRANSPARENT);
+		scene.setCamera(camera);
+
+		// First person shooter keyboard movement
+		scene.setOnKeyPressed(event -> {
+			double change = 10.0;
+			// Add shift modifier to simulate "Running Speed"
+			if (event.isShiftDown()) {
+				change = 50.0;
+			}
+			// What key did the user press?
+			final KeyCode keycode = event.getCode();
+			// Step 2c: Add Zoom controls
+			if (keycode == KeyCode.W) {
+				camera.setTranslateZ(camera.getTranslateZ() + change);
+			}
+			if (keycode == KeyCode.S) {
+				camera.setTranslateZ(camera.getTranslateZ() - change);
+			}
+			// Step 2d: Add Strafe controls
+			if (keycode == KeyCode.A) {
+				camera.setTranslateX(camera.getTranslateX() - change);
+			}
+			if (keycode == KeyCode.D) {
+				camera.setTranslateX(camera.getTranslateX() + change);
+			}
+		});
+
+		scene.setOnMousePressed((MouseEvent me) -> {
+			mousePosX = me.getSceneX();
+			mousePosY = me.getSceneY();
+			mouseOldX = me.getSceneX();
+			mouseOldY = me.getSceneY();
+		});
+		scene.setOnMouseDragged((MouseEvent me) -> {
+			mouseOldX = mousePosX;
+			mouseOldY = mousePosY;
+			mousePosX = me.getSceneX();
+			mousePosY = me.getSceneY();
+			mouseDeltaX = mousePosX - mouseOldX;
+			mouseDeltaY = mousePosY - mouseOldY;
+
+			double modifier = 10.0;
+			final double modifierFactor = 0.1;
+
+			if (me.isControlDown()) {
+				modifier = 0.1;
+			}
+			if (me.isShiftDown()) {
+				modifier = 50.0;
+			}
+			if (me.isPrimaryButtonDown()) {
+				cameraTransform.ry.setAngle(
+						((cameraTransform.ry.getAngle() + mouseDeltaX * modifierFactor * modifier * 2.0) % 360 + 540)
+								% 360 - 180); // +
+				cameraTransform.rx.setAngle(
+						((cameraTransform.rx.getAngle() - mouseDeltaY * modifierFactor * modifier * 2.0) % 360 + 540)
+								% 360 - 180); // -
+
+			} else if (me.isSecondaryButtonDown()) {
+				final double z = camera.getTranslateZ();
+				final double newZ = z + mouseDeltaX * modifierFactor * modifier;
+				camera.setTranslateZ(newZ);
+			} else if (me.isMiddleButtonDown()) {
+				cameraTransform.t.setX(cameraTransform.t.getX() + mouseDeltaX * modifierFactor * modifier * 0.3); // -
+				cameraTransform.t.setY(cameraTransform.t.getY() + mouseDeltaY * modifierFactor * modifier * 0.3); // -
+			}
+		});
+
+		/*scene.widthProperty().addListener(new ChangeListener<Number>() {
+		    @Override public void changed(ObservableValue<? extends Number> observableValue, Number oldSceneWidth, Number newSceneWidth) {
+		        System.out.println("Width: " + newSceneWidth);
+		    }
+
+			@Override
+			public void changed(ObservableValue<? extends Number> observable, Number oldSceneWidth, Number newSceneWidth) {
+				draw();
+			}
+		});*/
+		/*scene.heightProperty().addListener(new ChangeListener<Number>() {
+		    @Override public void changed(ObservableValue<? extends Number> observableValue, Number oldSceneHeight, Number newSceneHeight) {
+		        //System.out.println("Height: " + newSceneHeight);
+		    	draw();
+		    }
+		});*/
+
+		root.getChildren().addAll(cubemapBox, subGroup);
+		root.setAutoSizeChildren(true);
+
+		subGroup.setAutoSizeChildren(true);
+
+		// TODO: attempt to prevent content from disappearing after resizing
+		Platform.setImplicitExit(false);
+
+		return scene;
+	}
+
+	private static Scene createDefaultScene() {
+		// TODO: default scene with message? @rrh
+
+		// Load Cubemap box AFTER camera is initialized
+		final double size = 100000D;
+
+		TextArea textArea = new TextArea();
+		textArea.setText("No Streetside image selected.");
+
+		VBox vbox = new VBox(textArea);
+
+		Scene scene = new Scene(vbox, 200, 100);
+		return scene;
+	}
+
+	public static Scene createScene(BufferedImage img0, BufferedImage img1, BufferedImage img2, BufferedImage img3,
+			BufferedImage img4, BufferedImage img5) throws NonInvertibleTransformException {
+		front = GraphicsUtils.convertBufferedImage2JavaFXImage(img0);
+		right = GraphicsUtils.convertBufferedImage2JavaFXImage(img1);
+		back = GraphicsUtils.convertBufferedImage2JavaFXImage(img2);
+		left = GraphicsUtils.convertBufferedImage2JavaFXImage(img3);
+		up = GraphicsUtils.convertBufferedImage2JavaFXImage(img4);
+		down = GraphicsUtils.convertBufferedImage2JavaFXImage(img5);
+
+		root = new Group();
+
+		camera = new PerspectiveCamera(true);
+		cameraTransform.setTranslate(0, 0, 0);
+		cameraTransform.getChildren().addAll(camera);
+		camera.setNearClip(0.1);
+		camera.setFarClip(1000000.0);
+		camera.setFieldOfView(42);
+		camera.setTranslateZ(-cameraDistance);
+		// cameraTransform.ry.setAngle(-45.0);
+		// cameraTransform.rx.setAngle(-10.0);
+		// add a Point Light for better viewing of the grid coordinate system
+		final PointLight light = new PointLight(Color.WHITE);
+
+		cameraTransform.getChildren().add(light);
+		light.setTranslateX(camera.getTranslateX());
+		light.setTranslateY(camera.getTranslateY());
+		light.setTranslateZ(camera.getTranslateZ());
+
+		root.getChildren().add(cameraTransform);
+
+		// Load Cubemap box AFTER camera is initialized
+		final double size = 100000D;
+
+		cubemapBox = new CubemapBox(front, right, back, left, up, down, size, camera);
+
+		final Group torusGroup = new Group();
+		torusGroup.getChildren().add(cameraTransform);
+
+		final Scene scene = new Scene(new Group(root), 1024, 668, true, SceneAntialiasing.BALANCED);
+		scene.setFill(Color.TRANSPARENT);
+		scene.setCamera(camera);
+
+		// First person shooter keyboard movement
+		scene.setOnKeyPressed(event -> {
+			double change = 10.0;
+			// Add shift modifier to simulate "Running Speed"
+			if (event.isShiftDown()) {
+				change = 50.0;
+			}
+			// What key did the user press?
+			final KeyCode keycode = event.getCode();
+			// Step 2c: Add Zoom controls
+			if (keycode == KeyCode.W) {
+				camera.setTranslateZ(camera.getTranslateZ() + change);
+			}
+			if (keycode == KeyCode.S) {
+				camera.setTranslateZ(camera.getTranslateZ() - change);
+			}
+			// Step 2d: Add Strafe controls
+			if (keycode == KeyCode.A) {
+				camera.setTranslateX(camera.getTranslateX() - change);
+			}
+			if (keycode == KeyCode.D) {
+				camera.setTranslateX(camera.getTranslateX() + change);
+			}
+
+		});
+
+		scene.setOnMousePressed((MouseEvent me) -> {
+			mousePosX = me.getSceneX();
+			mousePosY = me.getSceneY();
+			mouseOldX = me.getSceneX();
+			mouseOldY = me.getSceneY();
+		});
+		scene.setOnMouseDragged((MouseEvent me) -> {
+			mouseOldX = mousePosX;
+			mouseOldY = mousePosY;
+			mousePosX = me.getSceneX();
+			mousePosY = me.getSceneY();
+			mouseDeltaX = mousePosX - mouseOldX;
+			mouseDeltaY = mousePosY - mouseOldY;
+
+			double modifier = 10.0;
+			final double modifierFactor = 0.1;
+
+			if (me.isControlDown()) {
+				modifier = 0.1;
+			}
+			if (me.isShiftDown()) {
+				modifier = 50.0;
+			}
+			if (me.isPrimaryButtonDown()) {
+				cameraTransform.ry.setAngle(
+						((cameraTransform.ry.getAngle() + mouseDeltaX * modifierFactor * modifier * 2.0) % 360 + 540)
+								% 360 - 180); // +
+				cameraTransform.rx.setAngle(
+						((cameraTransform.rx.getAngle() - mouseDeltaY * modifierFactor * modifier * 2.0) % 360 + 540)
+								% 360 - 180); // -
+
+			} else if (me.isSecondaryButtonDown()) {
+				final double z = camera.getTranslateZ();
+				final double newZ = z + mouseDeltaX * modifierFactor * modifier;
+				camera.setTranslateZ(newZ);
+			} else if (me.isMiddleButtonDown()) {
+				cameraTransform.t.setX(cameraTransform.t.getX() + mouseDeltaX * modifierFactor * modifier * 0.3); // -
+				cameraTransform.t.setY(cameraTransform.t.getY() + mouseDeltaY * modifierFactor * modifier * 0.3); // -
+			}
+		});
+
+		root.getChildren().addAll(cubemapBox, torusGroup);
+		root.setAutoSizeChildren(true);
+
+		return scene;
+	}
+
+	/*public void setCubemapImages(BufferedImage img, BufferedImage img1, BufferedImage img2, BufferedImage img3,
+			BufferedImage img4, BufferedImage img5) {
+		cubemapBox = null;
+
+		GraphicsUtils.PlatformHelper.run(new Runnable() {
+			@Override
+			public void run() {
+				try {
+					// initialize without imagery.
+					scene = createScene(img, img1, img2, img3, img4, img5);
+					setScene(scene);
+				} catch (NonInvertibleTransformException e) {
+					Logging.error(I18n.tr("Error initializing StreetsideViewerPanel - JavaFX {0}", e.getMessage()));
+				}
+			}
+		});
+	}*/
+
+	public CubemapBox getCubemapBox() {
+		if (cubemapBox == null) {
+			// shouldn't happen
+			initialize();
+		}
+		return cubemapBox;
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/WebLinkAction.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/WebLinkAction.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/imageinfo/WebLinkAction.java	(revision 34317)
@@ -0,0 +1,50 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui.imageinfo;
+
+import java.awt.event.ActionEvent;
+import java.io.IOException;
+import java.net.URL;
+
+import javax.swing.AbstractAction;
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.gui.Notification;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideUtils;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
+import org.openstreetmap.josm.tools.Logging;
+
+public class WebLinkAction extends AbstractAction {
+
+  private static final long serialVersionUID = -8168227661356480455L;
+
+  private URL url;
+
+  public WebLinkAction(final String name, final URL url) {
+    super(name, ImageProvider.get("link", ImageSizes.SMALLICON));
+    setURL(url);
+  }
+
+  /**
+   * @param url the url to set
+   */
+  public final void setURL(URL url) {
+    this.url = url;
+    setEnabled(url != null);
+  }
+
+  /* (non-Javadoc)
+   * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
+   */
+  @Override
+  public void actionPerformed(ActionEvent e) {
+    try {
+      StreetsideUtils.browse(url);
+    } catch (IOException e1) {
+      String msg = I18n.tr("Could not open the URL {0} in a browser", url == null ? "‹null›" : url);
+      Logging.log(Logging.LEVEL_WARN, msg, e1);
+      new Notification(msg).setIcon(JOptionPane.WARNING_MESSAGE).show();
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/package-info.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/package-info.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/gui/package-info.java	(revision 34317)
@@ -0,0 +1,5 @@
+// License: GPL. For details, see LICENSE file.
+/**
+ * The GUI components that are special to the mapillary plugin.
+ */
+package org.openstreetmap.josm.plugins.streetside.gui;
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/StreetsideRecord.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/StreetsideRecord.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/StreetsideRecord.java	(revision 34317)
@@ -0,0 +1,138 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.history;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+
+import org.openstreetmap.josm.plugins.streetside.history.commands.StreetsideCommand;
+import org.openstreetmap.josm.plugins.streetside.history.commands.StreetsideExecutableCommand;
+
+/**
+* History record system in order to let the user undo and redo commands.
+*
+* @author nokutu
+*
+*/
+public class StreetsideRecord {
+/** The unique instance of the class. */
+private static StreetsideRecord instance;
+
+private final List<StreetsideRecordListener> listeners = new ArrayList<>();
+
+/** The set of commands that have taken place or that have been undone. */
+public List<StreetsideCommand> commandList;
+/** Last written command. */
+public int position;
+
+/**
+* Main constructor.
+*/
+public StreetsideRecord() {
+ this.commandList = new ArrayList<>();
+ this.position = -1;
+}
+
+/**
+* Returns the unique instance of the class.
+*
+* @return The unique instance of the class.
+*/
+public static synchronized StreetsideRecord getInstance() {
+ if (StreetsideRecord.instance == null)
+   StreetsideRecord.instance = new StreetsideRecord();
+ return StreetsideRecord.instance;
+}
+
+/**
+* Adds a listener.
+*
+* @param lis
+*          The listener to be added.
+*/
+public void addListener(StreetsideRecordListener lis) {
+ this.listeners.add(lis);
+}
+
+/**
+* Removes the given listener.
+*
+* @param lis
+*          The listener to be removed.
+*/
+public void removeListener(StreetsideRecordListener lis) {
+ this.listeners.remove(lis);
+}
+
+/**
+* Adds a new command to the list.
+*
+* @param command
+*          The command to be added.
+*/
+public void addCommand(final StreetsideCommand command) {
+
+ if (command instanceof StreetsideExecutableCommand)
+   ((StreetsideExecutableCommand) command).execute();
+ // Checks if it is a continuation of last command
+ if (this.position != -1) {
+   boolean equalSets = true;
+   for (StreetsideAbstractImage img : this.commandList.get(this.position).images) {
+     equalSets = command.images.contains(img) && equalSets;
+   }
+   for (StreetsideAbstractImage img : command.images) {
+     equalSets = this.commandList.get(this.position).images.contains(img) && equalSets;
+   }
+   if (equalSets && this.commandList.get(this.position).getClass() == command.getClass()) {
+     this.commandList.get(this.position).sum(command);
+     fireRecordChanged();
+     return;
+   }
+ }
+ // Adds the command to the last position of the list.
+ this.commandList.add(this.position + 1, command);
+ this.position++;
+ while (this.commandList.size() > this.position + 1) {
+   this.commandList.remove(this.position + 1);
+ }
+ fireRecordChanged();
+}
+
+/**
+* Undo latest command.
+*/
+public void undo() {
+ if (this.position <= -1) {
+   return;
+ }
+ this.commandList.get(this.position).undo();
+ this.position--;
+ fireRecordChanged();
+}
+
+/**
+* Redoes latest undone action.
+*/
+public void redo() {
+ if (position + 1 >= commandList.size()) {
+   return;
+ }
+ this.position++;
+ this.commandList.get(this.position).redo();
+ fireRecordChanged();
+}
+
+private void fireRecordChanged() {
+ this.listeners.stream().filter(Objects::nonNull).forEach(StreetsideRecordListener::recordChanged);
+}
+
+/**
+* Resets the object to its start state.
+*/
+public void reset() {
+ this.commandList.clear();
+ this.position = -1;
+}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/StreetsideRecordListener.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/StreetsideRecordListener.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/StreetsideRecordListener.java	(revision 34317)
@@ -0,0 +1,17 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.history;
+
+/**
+* Interface for the listener of the {@link StreetsideRecord} class
+*
+* @author nokutu
+* @see StreetsideRecord
+*/
+@FunctionalInterface
+public interface StreetsideRecordListener {
+
+/**
+* Fired when any command is undone or redone.
+*/
+void recordChanged();
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandImport.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandImport.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandImport.java	(revision 34317)
@@ -0,0 +1,59 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.history.commands;
+
+import static org.openstreetmap.josm.tools.I18n.trn;
+
+import java.util.Set;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+
+
+/**
+ * Imports a set of images stored locally.
+ *
+ * @author nokutu
+ *
+ */
+public class CommandImport extends StreetsideExecutableCommand {
+
+  /**
+   * Main constructor.
+   *
+   * @param images
+   *          The set of images that are going to be added. Might be in the same
+   *          sequence or not.
+   */
+  public CommandImport(Set<StreetsideAbstractImage> images) {
+    super(images);
+  }
+
+  @Override
+  public void execute() {
+    StreetsideLayer.getInstance().getData().addAll(this.images);
+  }
+
+  @Override
+  public void undo() {
+    for (StreetsideAbstractImage img : this.images) {
+      StreetsideLayer.getInstance().getData().getImages().remove(img);
+    }
+    StreetsideLayer.invalidateInstance();
+  }
+
+  @Override
+  public void redo() {
+    this.execute();
+  }
+
+  @Override
+  public void sum(StreetsideCommand command) {
+  }
+
+  @Override
+  public String toString() {
+    // TODO: trn( RRH
+    return trn("Imported {0} image", "Imported {0} images", this.images.size(),
+        this.images.size());
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandJoin.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandJoin.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandJoin.java	(revision 34317)
@@ -0,0 +1,63 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.history.commands;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideUtils;
+
+/**
+ * Command joined when joining two images into the same sequence.
+ *
+ * @author nokutu
+ *
+ */
+public class CommandJoin extends StreetsideExecutableCommand {
+
+  private final StreetsideAbstractImage a;
+  private final StreetsideAbstractImage b;
+
+  /**
+   * Main constructor.
+   *
+   * @param a the first image, that is joined with the second one
+   * @param b the second image, that is joined with the first one
+   * @throws IllegalArgumentException if the images are already in the same sequence
+   * @throws NullPointerException if {@code a} or {@code b} is null
+   */
+  public CommandJoin(final StreetsideAbstractImage a, final StreetsideAbstractImage b) {
+    super(new ConcurrentSkipListSet<>(Arrays.asList(a, b))); // throws NPE if a or b is null
+    if (a.getSequence() == b.getSequence()) {
+      throw new IllegalArgumentException("Both images must be in different sequences for joining.");
+    }
+    this.a = a;
+    this.b = b;
+  }
+
+  @Override
+  public void execute() {
+    redo();
+  }
+
+  @Override
+  public void undo() {
+    StreetsideUtils.unjoin(a, b);
+  }
+
+  @Override
+  public void redo() {
+    StreetsideUtils.join(a, b);
+  }
+
+  @Override
+  public void sum(StreetsideCommand command) {
+  }
+
+  @Override
+  public String toString() {
+    return tr("2 images joined");
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandMove.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandMove.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandMove.java	(revision 34317)
@@ -0,0 +1,70 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.history.commands;
+
+import static org.openstreetmap.josm.tools.I18n.trn;
+
+import java.util.Set;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+
+/**
+ * Command created when an image's position is changed.
+ *
+ * @author nokutu
+ *
+ */
+public class CommandMove extends StreetsideCommand {
+  private double x;
+  private double y;
+
+  /**
+   * Main constructor.
+   *
+   * @param images
+   *          Set of images that are going to be moved.
+   * @param x
+   *          How much the x coordinate increases.
+   * @param y
+   *          How much the y coordinate increases.
+   */
+  public CommandMove(Set<StreetsideAbstractImage> images, double x,
+                     double y) {
+    super(images);
+    this.x = x;
+    this.y = y;
+  }
+
+  @Override
+  public void undo() {
+    for (StreetsideAbstractImage image : this.images) {
+      image.move(-this.x, -this.y);
+      image.stopMoving();
+    }
+    StreetsideLayer.invalidateInstance();
+  }
+
+  @Override
+  public void redo() {
+    for (StreetsideAbstractImage image : this.images) {
+      image.move(this.x, this.y);
+      image.stopMoving();
+    }
+    StreetsideLayer.invalidateInstance();
+  }
+
+  @Override
+  public String toString() {
+    // TODO: trn( RRH
+    return trn("Moved {0} image", "Moved {0} images", this.images.size(),
+        this.images.size());
+  }
+
+  @Override
+  public void sum(StreetsideCommand command) {
+    if (command instanceof CommandMove) {
+      this.x += ((CommandMove) command).x;
+      this.y += ((CommandMove) command).y;
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandTurn.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandTurn.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandTurn.java	(revision 34317)
@@ -0,0 +1,64 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.history.commands;
+
+import static org.openstreetmap.josm.tools.I18n.trn;
+
+import java.util.Set;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+
+/**
+ * Command created when an image's direction is changed.
+ *
+ * @author nokutu
+ *
+ */
+public class CommandTurn extends StreetsideCommand {
+  private double ca;
+
+  /**
+   * Main constructor.
+   *
+   * @param images
+   *          Set of images that is turned.
+   * @param cd
+   *          How much the images turn.
+   */
+  public CommandTurn(Set<StreetsideAbstractImage> images, double ca) {
+    super(images);
+    this.ca = ca;
+  }
+
+  @Override
+  public void undo() {
+    for (StreetsideAbstractImage image : this.images) {
+      image.turn(-this.ca);
+      image.stopMoving();
+    }
+    StreetsideLayer.invalidateInstance();
+  }
+
+  @Override
+  public void redo() {
+    for (StreetsideAbstractImage image : this.images) {
+      image.turn(this.ca);
+      image.stopMoving();
+    }
+    StreetsideLayer.invalidateInstance();
+  }
+
+  @Override
+  public String toString() {
+    // TODO: trn( RRH
+    return trn("Turned {0} image", "Turned {0} images", this.images.size(),
+        this.images.size());
+  }
+
+  @Override
+  public void sum(StreetsideCommand command) {
+    if (command instanceof CommandTurn) {
+      this.ca += ((CommandTurn) command).ca;
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandUnjoin.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandUnjoin.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/CommandUnjoin.java	(revision 34317)
@@ -0,0 +1,64 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.history.commands;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.util.List;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideUtils;
+
+/**
+ * Command joined when joining two images into the same sequence.
+ *
+ * @author nokutu
+ *
+ */
+public class CommandUnjoin extends StreetsideExecutableCommand {
+
+  private final StreetsideAbstractImage a;
+  private final StreetsideAbstractImage b;
+
+  /**
+   * Main constructor.
+   *
+   * @param images
+   *          The two images that are going to be unjoined. Must be of exactly
+   *          size 2.
+   * @throws IllegalArgumentException
+   *           if the List size is different from 2.
+   */
+  public CommandUnjoin(List<StreetsideAbstractImage> images) {
+    super(new ConcurrentSkipListSet<>(images));
+    a = images.get(0);
+    b = images.get(1);
+    if (images.size() != 2)
+      throw new IllegalArgumentException();
+  }
+
+  @Override
+  public void execute() {
+    this.redo();
+  }
+
+  @Override
+  public void undo() {
+    StreetsideUtils.join(a, b);
+  }
+
+  @Override
+  public void redo() {
+    StreetsideUtils.unjoin(a, b);
+  }
+
+  @Override
+  public void sum(StreetsideCommand command) {
+  }
+
+  @Override
+  public String toString() {
+    // TODO: tr( RRH
+    return tr("2 images unjoined");
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/StreetsideCommand.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/StreetsideCommand.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/StreetsideCommand.java	(revision 34317)
@@ -0,0 +1,50 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.history.commands;
+
+import java.util.Set;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+
+/**
+* Abstract class for any Streetside command.
+*
+* @author nokutu
+*
+*/
+public abstract class StreetsideCommand {
+/** Set of {@link StreetsideAbstractImage} objects affected by the command */
+public Set<StreetsideAbstractImage> images;
+
+/**
+* Main constructor.
+*
+* @param images
+*          The images that are affected by the command.
+*/
+public StreetsideCommand(Set<StreetsideAbstractImage> images) {
+ this.images = new ConcurrentSkipListSet<>(images);
+}
+
+/**
+* Undoes the action.
+*/
+public abstract void undo();
+
+/**
+* Redoes the action.
+*/
+public abstract void redo();
+
+/**
+* If two equal commands are applied consecutively to the same set of images,
+* they are summed in order to reduce them to just one command.
+*
+* @param command
+*          The command to be summed to last command.
+*/
+public abstract void sum(StreetsideCommand command);
+
+@Override
+public abstract String toString();
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/StreetsideExecutableCommand.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/StreetsideExecutableCommand.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/commands/StreetsideExecutableCommand.java	(revision 34317)
@@ -0,0 +1,31 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.history.commands;
+
+import java.util.Set;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+
+/**
+* Superclass for those commands that must be executed after creation.
+*
+* @author nokutu
+*
+*/
+public abstract class StreetsideExecutableCommand extends StreetsideCommand {
+
+/**
+* Main constructor.
+*
+* @param images
+*          The set of images affected by the command.
+*/
+public StreetsideExecutableCommand(Set<StreetsideAbstractImage> images) {
+ super(images);
+}
+
+/**
+* Executes the command. It is run when the command is added to the history
+* record.
+*/
+public abstract void execute();
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/package-info.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/package-info.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/history/package-info.java	(revision 34317)
@@ -0,0 +1,6 @@
+// License: GPL. For details, see LICENSE file.
+/**
+ * This package deals with keeping a history of actions the user performed
+ * to allow for undoing and redoing these actions.
+ */
+package org.openstreetmap.josm.plugins.streetside.history;
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/BoundsDownloadRunnable.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/BoundsDownloadRunnable.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/BoundsDownloadRunnable.java	(revision 34317)
@@ -0,0 +1,79 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.io.download;
+
+import java.awt.GraphicsEnvironment;
+import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.function.Function;
+
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.gui.Notification;
+import org.openstreetmap.josm.plugins.streetside.StreetsidePlugin;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.ImageProvider.ImageSizes;
+import org.openstreetmap.josm.tools.Logging;
+
+public abstract class BoundsDownloadRunnable implements Runnable {
+
+  protected Bounds bounds;
+  protected abstract Function<Bounds, URL> getUrlGenerator();
+
+  public BoundsDownloadRunnable(final Bounds bounds) {
+    this.bounds = bounds;
+  }
+
+  @Override
+  public void run() {
+    URL nextURL = getUrlGenerator().apply(bounds);
+    try {
+      while (nextURL != null) {
+        if (Thread.interrupted()) {
+          Logging.debug("{} for {} interrupted!", getClass().getSimpleName(), bounds.toString());
+          return;
+        }
+        final URLConnection con = nextURL.openConnection();
+        run(con);
+        nextURL = APIv3.parseNextFromLinkHeaderValue(con.getHeaderField("Link"));
+      }
+    } catch (IOException e) {
+      String message = I18n.tr("Could not read from URL {0}!", nextURL.toString());
+      Logging.log(Logging.LEVEL_WARN, message, e);
+      if (!GraphicsEnvironment.isHeadless()) {
+        new Notification(message)
+          .setIcon(StreetsidePlugin.LOGO.setSize(ImageSizes.LARGEICON).get())
+          .setDuration(Notification.TIME_LONG)
+          .show();
+      }
+      e.printStackTrace();
+    }
+  }
+
+  /**
+   * Logs information about the given connection via {@link Logging#info(String)}.
+   * If it's a {@link HttpURLConnection}, the request method, the response code and the URL itself are logged.
+   * Otherwise only the URL is logged.
+   * @param con the {@link URLConnection} for which information is logged
+   * @param info an additional info text, which is appended to the output in braces
+   * @throws IOException if {@link HttpURLConnection#getResponseCode()} throws an {@link IOException}
+   */
+  public static void logConnectionInfo(final URLConnection con, final String info) throws IOException {
+    final StringBuilder message;
+    if (con instanceof HttpURLConnection) {
+      message = new StringBuilder(((HttpURLConnection) con).getRequestMethod())
+        .append(' ').append(con.getURL())
+        .append(" → ").append(((HttpURLConnection) con).getResponseCode());
+    } else {
+      message = new StringBuilder("Download from ").append(con.getURL());
+    }
+    if (info != null && info.length() >= 1) {
+      message.append(" (").append(info).append(')');
+    }
+    Logging.info(message.toString());
+  }
+
+  public abstract void run(final URLConnection connection) throws IOException;
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/ImageDetailsDownloadRunnable.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/ImageDetailsDownloadRunnable.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/ImageDetailsDownloadRunnable.java	(revision 34317)
@@ -0,0 +1,43 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.io.download;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.function.Function;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.plugins.streetside.StreetsideData;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3;
+
+
+public class ImageDetailsDownloadRunnable extends BoundsDownloadRunnable {
+  //private static final Function<Bounds, URL> URL_GEN = APIv3::searchImages;
+  private static final Function<Bounds, URL> URL_GEN = APIv3::searchStreetsideImages;
+
+  private final StreetsideData data;
+
+  public ImageDetailsDownloadRunnable(final StreetsideData data, final Bounds bounds) {
+    super(bounds);
+    this.data = data;
+  }
+
+  // TODO: image infos for 360 degree viewer? @rrh
+  @Override
+  public void run(final URLConnection con) throws IOException {
+     // TODO: modifiy decoder to handle Streetside image info. @rrh
+	  /*try (JsonReader reader = Json.createReader(new BufferedInputStream(con.getInputStream()))) {
+      JsonImageDetailsDecoder.decodeImageInfos(reader.readObject(), data);
+      logConnectionInfo(con, null);
+      StreetsideMainDialog.getInstance().updateTitle();
+    } catch (JsonException | NumberFormatException e) {
+      throw new IOException(e);
+    }*/
+  }
+
+  @Override
+  protected Function<Bounds, URL> getUrlGenerator() {
+    return URL_GEN;
+  }
+
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/SequenceDownloadRunnable.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/SequenceDownloadRunnable.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/SequenceDownloadRunnable.java	(revision 34317)
@@ -0,0 +1,200 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.io.download;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.function.Function;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideData;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideSequence;
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideSequenceIdGenerator;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.Logging;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+public final class SequenceDownloadRunnable extends BoundsDownloadRunnable {
+
+	private final StreetsideData data;
+
+  private static final Function<Bounds, URL> URL_GEN = APIv3::searchStreetsideSequences;
+
+  public SequenceDownloadRunnable(final StreetsideData data, final Bounds bounds) {
+    super(bounds);
+    this.data = data;
+  }
+
+  @Override
+  public void run(final URLConnection con) throws IOException {
+    if (Thread.interrupted()) {
+      return;
+    }
+
+    StreetsideSequence seq = new StreetsideSequence(StreetsideSequenceIdGenerator.generateId());
+
+    // TODO: how can LatLon and heading / camera angles (he attribute) be set for a sequence?
+    // and does it make sense? @rrh
+
+    List<StreetsideImage> bubbleImages = new ArrayList<>();
+
+    final long startTime = System.currentTimeMillis();
+
+    ObjectMapper mapper = new ObjectMapper();
+    // Creation of Jackson Object Mapper necessary for Silverlight 2.0 JSON Syntax parsing:
+    // (no double quotes in JSON on attribute names)
+    mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
+
+    // Allow unrecognized properties - won't break with addition of new attributes
+    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+
+    try {
+
+    JsonParser parser = mapper.getFactory().createParser(new BufferedInputStream(con.getInputStream()));
+    if(parser.nextToken() != JsonToken.START_ARRAY) {
+      parser.close();
+      throw new IllegalStateException("Expected an array");
+    }
+
+
+    StreetsideImage previous = null;
+
+    while (parser.nextToken() == JsonToken.START_OBJECT) {
+        // read everything from this START_OBJECT to the matching END_OBJECT
+        // and return it as a tree model ObjectNode
+        ObjectNode node = mapper.readTree(parser);
+        // Discard the first sequence ('enabled') - it does not contain bubble data
+        if (node.get("id") != null && node.get("la") != null && node.get("lo") != null) {
+          StreetsideImage image = new StreetsideImage(CubemapUtils.convertDecimal2Quaternary(node.path("id").asLong()), node.path("la").asDouble(), node.get("lo").asDouble());
+          if(previous!=null) {
+        	  // Analyze sequence behaviour
+        	  //previous.setNext(image.)
+          }
+          image.setAd(node.path("ad").asInt());
+          image.setAl(node.path("al").asDouble());
+          image.setBl(node.path("bl").asText());
+          image.setCd(node.path("cd").asLong());
+          image.setHe(node.path("he").asDouble());
+          image.setMl(node.path("ml").asInt());
+          image.setNbn(node.findValuesAsText("nbn"));
+          image.setNe(node.path("ne").asLong());
+          image.setPbn(node.findValuesAsText("pbn"));
+          image.setPi(node.path("pi").asDouble());
+          image.setPr(node.path("pr").asLong());
+          // TODO: inner class @rrh
+          // image.setRn(node.path("rn").asText());
+          image.setRo(node.path("ro").asDouble());
+
+          // Add list of cubemap tile images to images
+          List<StreetsideImage> tiles = new ArrayList<StreetsideImage>();
+
+        // TODO: set previous and next @rrh
+
+					EnumSet.allOf(CubemapUtils.CubemapFaces.class).forEach(face -> {
+
+							for (int i = 0; i < 4; i++) {
+								// Initialize four-tiled cubemap faces (four images per cube side with 18-length
+								// Quadkey)
+								//if (StreetsideProperties.CUBEFACE_SIZE.get().intValue() == 4) {
+								if (!StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {
+									StreetsideImage tile = new StreetsideImage(
+											String.valueOf(image.getId() + Integer.valueOf(i)));
+									tiles.add(tile);
+								}
+								// Initialize four-tiled cubemap faces (four images per cub eside with 20-length
+								// Quadkey)
+								//if (StreetsideProperties.CUBEFACE_SIZE.get().intValue() == 16) {
+								if (StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get()) {
+									for (int j = 0; j < 4; j++) {
+										StreetsideImage tile = new StreetsideImage(String.valueOf(image.getId()
+												+ face.getValue() + CubemapUtils.rowCol2StreetsideCellAddressMap
+														.get(String.valueOf(Integer.valueOf(i).toString() + Integer.valueOf(j).toString()))));
+										tiles.add(tile);
+									}
+								}
+							}
+					});
+
+      	  bubbleImages.add(image);
+          Logging.info("Added image with id <" + image.getId() + ">");
+          // TODO: double check whether this pre-caches successfullly @rrh
+          //StreetsideData.downloadSurroundingCubemaps(image);
+
+        }
+      }
+
+    parser.close();
+
+    //StreetsideImage[] images;
+
+      // First load all of the 'bubbles' from the request as Streetside Images
+      /*List<StreetsideImage> images = mapper
+        .readValue(new BufferedInputStream(con.getInputStream()), new TypeReference<List<StreetsideImage>>() {});
+      */
+
+
+      //images = mapper.readValue(new BufferedInputStream(con.getInputStream()), StreetsideImage[].class);
+
+      /*for (StreetsideImage image : bubbleImages) {
+        image = JsonStreetsideSequencesDecoder.decodeBubbleData(image);
+        if(image != null) bubbleImages.add(image);
+      }*/
+
+    } catch (JsonParseException e) {
+      e.printStackTrace();
+    } catch (JsonMappingException e) {
+      e.printStackTrace();
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+
+    /** Top Level Bubble Metadata in Streetside are bubble (aka images) not Sequences
+     *  so a sequence needs to be created and have images added to it. If the distribution
+     *  of Streetside images is non-sequential, the Mapillary "Walking Action" may behave
+     *  unpredictably.
+     **/
+    seq.add(bubbleImages);
+
+    if (StreetsideProperties.CUT_OFF_SEQUENCES_AT_BOUNDS.get()) {
+      for (StreetsideAbstractImage img : seq.getImages()) {
+        if (bounds.contains(img.getLatLon())) {
+          data.add(img);
+        } else {
+          seq.remove(img);
+        }
+      }
+    } else {
+      boolean sequenceCrossesThroughBounds = false;
+      for (int i = 0; i < seq.getImages().size() && !sequenceCrossesThroughBounds; i++) {
+        sequenceCrossesThroughBounds = bounds.contains(seq.getImages().get(i).getLatLon());
+      }
+      if (sequenceCrossesThroughBounds) {
+        data.addAll(seq.getImages(), true);
+      }
+    }
+
+    final long endTime = System.currentTimeMillis();
+    Logging.info(I18n.tr("Sucessfully loaded {0} Microsoft Streetside images in {0} ",seq.getImages().size(),endTime-startTime%60));
+  }
+
+  @Override
+  protected Function<Bounds, URL> getUrlGenerator() {
+    return URL_GEN;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/StreetsideDownloader.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/StreetsideDownloader.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/StreetsideDownloader.java	(revision 34317)
@@ -0,0 +1,232 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.io.download;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.Notification;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.StreetsidePlugin;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+ * Class that concentrates all the ways of downloading of the plugin. All the
+ * download petitions will be managed one by one.
+ *
+ * @author nokutu
+ */
+public final class StreetsideDownloader {
+
+  /** Possible download modes. */
+  public enum DOWNLOAD_MODE {
+    // i18n: download mode for Streetside images
+    VISIBLE_AREA("visibleArea", I18n.tr("everything in the visible area")),
+    // i18n: download mode for Streetside images
+    OSM_AREA("osmArea", I18n.tr("areas with downloaded OSM-data")),
+    // i18n: download mode for Streetside images
+    MANUAL_ONLY("manualOnly", I18n.tr("only when manually requested"));
+
+    public final static DOWNLOAD_MODE DEFAULT = OSM_AREA;
+
+    private final String prefId;
+    private final String label;
+
+    DOWNLOAD_MODE(String prefId, String label) {
+      this.prefId = prefId;
+      this.label = label;
+    }
+
+    /**
+     * @return the ID that is used to represent this download mode in the JOSM preferences
+     */
+    public String getPrefId() {
+      return prefId;
+    }
+
+    /**
+     * @return the (internationalized) label describing this download mode
+     */
+    public String getLabel() {
+      return label;
+    }
+
+    public static DOWNLOAD_MODE fromPrefId(String prefId) {
+      for (DOWNLOAD_MODE mode : DOWNLOAD_MODE.values()) {
+        if (mode.getPrefId().equals(prefId)) {
+          return mode;
+        }
+      }
+      return DEFAULT;
+    }
+
+    public static DOWNLOAD_MODE fromLabel(String label) {
+      for (DOWNLOAD_MODE mode : DOWNLOAD_MODE.values()) {
+        if (mode.getLabel().equals(label)) {
+          return mode;
+        }
+      }
+      return DEFAULT;
+    }
+  }
+
+  /** Max area to be downloaded */
+  private static final double MAX_AREA = StreetsideProperties.MAX_DOWNLOAD_AREA.get();
+
+  /** Executor that will run the petitions. */
+  private static ThreadPoolExecutor executor = new ThreadPoolExecutor(
+    3, 5, 100, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), new ThreadPoolExecutor.DiscardPolicy());
+
+  /**
+   * Indicates whether the last download request has been rejected because it requested an area that was too big.
+   * Iff true, the last download has been rejected, if false, it was executed.
+   */
+  private static boolean stoppedDownload;
+
+  private StreetsideDownloader() {
+    // Private constructor to avoid instantiation
+  }
+
+  /**
+   * Gets all the images in a square. It downloads all the images of all the
+   * sequences that pass through the given rectangle.
+   *
+   * @param minLatLon The minimum latitude and longitude of the rectangle.
+   * @param maxLatLon The maximum latitude and longitude of the rectangle
+   */
+  public static void getImages(LatLon minLatLon, LatLon maxLatLon) {
+    if (minLatLon == null || maxLatLon == null) {
+      throw new IllegalArgumentException();
+    }
+    getImages(new Bounds(minLatLon, maxLatLon));
+  }
+
+  /**
+   * Gets the images within the given bounds.
+   *
+   * @param bounds A {@link Bounds} object containing the area to be downloaded.
+   */
+  public static void getImages(Bounds bounds) {
+    run(new StreetsideSquareDownloadRunnable(bounds));
+  }
+
+  /**
+   * Returns the current download mode.
+   *
+   * @return the currently enabled {@link DOWNLOAD_MODE}
+   */
+  public static DOWNLOAD_MODE getMode() {
+    return DOWNLOAD_MODE.fromPrefId(StreetsideProperties.DOWNLOAD_MODE.get());
+  }
+
+  private static void run(Runnable t) {
+    executor.execute(t);
+  }
+
+  /**
+   * If some part of the current view has not been downloaded, it is downloaded.
+   */
+  public static void downloadVisibleArea() {
+    Bounds view = MainApplication.getMap().mapView.getRealBounds();
+    if (isAreaTooBig(view.getArea())) {
+      return;
+    }
+    if (isViewDownloaded(view)) {
+      return;
+    }
+    StreetsideLayer.getInstance().getData().getBounds().add(view);
+    getImages(view);
+  }
+
+  private static boolean isViewDownloaded(Bounds view) {
+    int n = 15;
+    boolean[][] inside = new boolean[n][n];
+    for (int i = 0; i < n; i++) {
+      for (int j = 0; j < n; j++) {
+        if (isInBounds(new LatLon(view.getMinLat()
+          + (view.getMaxLat() - view.getMinLat()) * ((double) i / n),
+          view.getMinLon() + (view.getMaxLon() - view.getMinLon())
+            * ((double) j / n)))) {
+          inside[i][j] = true;
+        }
+      }
+    }
+    for (int i = 0; i < n; i++) {
+      for (int j = 0; j < n; j++) {
+        if (!inside[i][j])
+          return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Checks if the given {@link LatLon} object lies inside the bounds of the
+   * image.
+   *
+   * @param latlon The coordinates to check.
+   *
+   * @return true if it lies inside the bounds; false otherwise;
+   */
+  private static boolean isInBounds(LatLon latlon) {
+    return StreetsideLayer.getInstance().getData().getBounds().parallelStream().anyMatch(b -> b.contains(latlon));
+  }
+
+  /**
+   * Downloads all images of the area covered by the OSM data.
+   */
+  public static void downloadOSMArea() {
+    if (MainApplication.getLayerManager().getEditLayer() == null) {
+      return;
+    }
+    if (isAreaTooBig(MainApplication.getLayerManager().getEditLayer().data.getDataSourceBounds().parallelStream().map(Bounds::getArea).reduce(0.0, Double::sum))) {
+      return;
+    }
+    MainApplication.getLayerManager().getEditLayer().data.getDataSourceBounds().stream().filter(bounds -> !StreetsideLayer.getInstance().getData().getBounds().contains(bounds)).forEach(bounds -> {
+      StreetsideLayer.getInstance().getData().getBounds().add(bounds);
+      StreetsideDownloader.getImages(bounds.getMin(), bounds.getMax());
+    });
+  }
+
+  /**
+   * Checks if the area for which Streetside images should be downloaded is too big. This means that probably
+   * lots of Streetside images are going to be downloaded, slowing down the
+   * program too much. A notification is shown when the download has stopped or continued.
+   */
+  private static boolean isAreaTooBig(final double area) {
+    final boolean tooBig = area > MAX_AREA;
+    if (!stoppedDownload && tooBig) {
+      new Notification(
+        I18n.tr("The Streetside layer has stopped downloading images, because the requested area is too big!") + (
+          getMode() == DOWNLOAD_MODE.VISIBLE_AREA
+          ? "\n"+I18n.tr("To solve this problem, you could zoom in and load a smaller area of the map.")
+          : (getMode() == DOWNLOAD_MODE.OSM_AREA ? "\n"+I18n.tr("To solve this problem, you could switch to download mode ''{0}'' and load Streetside images for a smaller portion of the map.", DOWNLOAD_MODE.MANUAL_ONLY): "")
+        )
+      ).setIcon(StreetsidePlugin.LOGO.get()).setDuration(Notification.TIME_LONG).show();
+    }
+    if (stoppedDownload && !tooBig) {
+      new Notification("The Streetside layer now continues to download images…").setIcon(StreetsidePlugin.LOGO.get()).show();
+    }
+    stoppedDownload = tooBig;
+    return tooBig;
+  }
+
+  /**
+   * Stops all running threads.
+   */
+  public static void stopAll() {
+    executor.shutdownNow();
+    try {
+      executor.awaitTermination(30, TimeUnit.SECONDS);
+    } catch (InterruptedException e) {
+      Logging.error(e);
+    }
+    executor = new ThreadPoolExecutor(3, 5, 100, TimeUnit.SECONDS,
+      new ArrayBlockingQueue<>(100), new ThreadPoolExecutor.DiscardPolicy());
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/StreetsideSquareDownloadRunnable.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/StreetsideSquareDownloadRunnable.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/StreetsideSquareDownloadRunnable.java	(revision 34317)
@@ -0,0 +1,61 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.io.download;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.gui.StreetsideMainDialog;
+import org.openstreetmap.josm.plugins.streetside.utils.PluginState;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideUtils;
+import org.openstreetmap.josm.tools.Logging;
+
+public class StreetsideSquareDownloadRunnable implements Runnable {
+
+  private final Bounds bounds;
+
+  /**
+   * Main constructor.
+   *
+   * @param bounds the bounds of the area that should be downloaded
+   *
+   */
+  public StreetsideSquareDownloadRunnable(Bounds bounds) {
+    this.bounds = bounds;
+  }
+
+  @Override
+  public void run() {
+    PluginState.startDownload();
+    StreetsideUtils.updateHelpText();
+
+    // Download basic sequence data synchronously
+    new SequenceDownloadRunnable(StreetsideLayer.getInstance().getData(), bounds).run();
+
+    if (Thread.interrupted()) {
+      return;
+    }
+
+    // TODO: Revamp image details for Streetside RRH
+    // Asynchronously load the rest of the image details
+    Thread imgDetailsThread = new Thread(new ImageDetailsDownloadRunnable(StreetsideLayer.getInstance().getData(), bounds));
+    imgDetailsThread.start();
+
+    // TODO: Do we support detections? RRH
+    /*Thread detectionsThread = new Thread(new DetectionsDownloadRunnable(StreetsideLayer.getInstance().getData(), bounds));
+    detectionsThread.start();*/
+
+    try {
+      imgDetailsThread.join();
+      //detectionsThread.join();
+    } catch (InterruptedException e) {
+      Logging.log(Logging.LEVEL_WARN, "Streetside download interrupted (probably because of closing the layer).", e);
+      Thread.currentThread().interrupt();
+    } finally {
+      PluginState.finishDownload();
+    }
+
+    StreetsideUtils.updateHelpText();
+    StreetsideLayer.invalidateInstance();
+    //StreetsideFilterDialog.getInstance().refresh();
+    StreetsideMainDialog.getInstance().updateImage();
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/package-info.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/package-info.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/download/package-info.java	(revision 34317)
@@ -0,0 +1,5 @@
+// License: GPL. For details, see LICENSE file.
+/**
+ * Classes for downloading images, sequences and image metadata like traffic signs from <a href="https://mapillary.com">mapillary.com</a> .
+ */
+package org.openstreetmap.josm.plugins.streetside.io.download;
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/StreetsideExportDownloadThread.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/StreetsideExportDownloadThread.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/StreetsideExportDownloadThread.java	(revision 34317)
@@ -0,0 +1,74 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.io.export;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.concurrent.ArrayBlockingQueue;
+
+import javax.imageio.ImageIO;
+
+import org.openstreetmap.josm.data.cache.CacheEntry;
+import org.openstreetmap.josm.data.cache.CacheEntryAttributes;
+import org.openstreetmap.josm.data.cache.ICachedLoaderListener;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.cache.CacheUtils;
+import org.openstreetmap.josm.plugins.streetside.cache.StreetsideCache;
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+ * This is the thread that downloads one of the images that are going to be
+ * exported and writes them in a {@link ArrayBlockingQueue}.
+ *
+ * @author nokutu
+ * @see StreetsideExportManager
+ * @see StreetsideExportWriterThread
+ */
+public class StreetsideExportDownloadThread extends Thread implements
+    ICachedLoaderListener {
+
+  private final ArrayBlockingQueue<BufferedImage> queue;
+  private final ArrayBlockingQueue<StreetsideAbstractImage> queueImages;
+
+  private final StreetsideImage image;
+
+  /**
+   * Main constructor.
+   *
+   * @param image
+   *          Image to be downloaded.
+   * @param queue
+   *          Queue of {@link BufferedImage} objects for the
+   *          {@link StreetsideExportWriterThread}.
+   * @param queueImages
+   *          Queue of {@link StreetsideAbstractImage} objects for the
+   *          {@link StreetsideExportWriterThread}.
+   */
+  public StreetsideExportDownloadThread(StreetsideImage image,
+      ArrayBlockingQueue<BufferedImage> queue,
+      ArrayBlockingQueue<StreetsideAbstractImage> queueImages) {
+    this.queue = queue;
+    this.image = image;
+    this.queueImages = queueImages;
+  }
+
+  @Override
+  public void run() {
+    CacheUtils.submit(this.image.getId(), StreetsideCache.Type.FULL_IMAGE, this);
+  }
+
+  @Override
+  public synchronized void loadingFinished(CacheEntry data,
+      CacheEntryAttributes attributes, LoadResult result) {
+    try {
+      synchronized (StreetsideExportDownloadThread.class) {
+        this.queue
+            .put(ImageIO.read(new ByteArrayInputStream(data.getContent())));
+        this.queueImages.put(this.image);
+      }
+    } catch (InterruptedException | IOException e) {
+      Logging.error(e);
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/StreetsideExportManager.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/StreetsideExportManager.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/StreetsideExportManager.java	(revision 34317)
@@ -0,0 +1,140 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.io.export;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.openstreetmap.josm.gui.PleaseWaitRunnable;
+import org.openstreetmap.josm.gui.progress.swing.PleaseWaitProgressMonitor;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImportedImage;
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+ * Export main thread. Exportation works by creating a
+ * {@link StreetsideExportWriterThread} and several
+ * {@link StreetsideExportDownloadThread}. The second ones download every single
+ * image that is going to be exported and stores them in an
+ * {@link ArrayBlockingQueue}. Then it is picked by the first one and written on
+ * the selected folder. Each image will be named by its key.
+ *
+ * @author nokutu
+ * @see StreetsideExportWriterThread
+ * @see StreetsideExportDownloadThread
+ */
+public class StreetsideExportManager extends PleaseWaitRunnable {
+
+  private final ArrayBlockingQueue<BufferedImage> queue = new ArrayBlockingQueue<>(10);
+  private final ArrayBlockingQueue<StreetsideAbstractImage> queueImages = new ArrayBlockingQueue<>(10);
+
+  private int amount;
+  private Set<StreetsideAbstractImage> images;
+  private String path;
+
+  private Thread writer;
+  private ThreadPoolExecutor ex;
+
+  /**
+   * Main constructor.
+   *
+   * @param images Set of {@link StreetsideAbstractImage} objects to be exported.
+   * @param path Export path.
+   */
+  public StreetsideExportManager(Set<StreetsideAbstractImage> images, String path) {
+    super(
+      tr("Downloading") + "…",
+      new PleaseWaitProgressMonitor(tr("Exporting Streetside Images")),
+      true
+    );
+    this.images = images == null ? new HashSet<>() : images;
+    this.path = path;
+    this.amount = this.images.size();
+  }
+
+  /**
+   * Constructor used to rewrite imported images.
+   *
+   * @param images
+   *          The set of {@link StreetsideImportedImage} object that is going to
+   *          be rewritten.
+   * @throws IOException
+   *           If the file of one of the {@link StreetsideImportedImage} objects
+   *           doesn't contain a picture.
+   */
+  public StreetsideExportManager(List<StreetsideImportedImage> images) throws IOException {
+    this(null, null);
+    for (StreetsideImportedImage image : images) {
+      this.queue.add(image.getImage());
+      this.queueImages.add(image);
+    }
+    this.amount = images.size();
+  }
+
+  @Override
+  protected void cancel() {
+    this.writer.interrupt();
+    this.ex.shutdown();
+  }
+
+  @Override
+  protected void realRun() throws IOException {
+    // Starts a writer thread in order to write the pictures on the disk.
+    this.writer = new StreetsideExportWriterThread(this.path, this.queue,
+        this.queueImages, this.amount, this.getProgressMonitor());
+    this.writer.start();
+    if (this.path == null) {
+      try {
+        this.writer.join();
+      } catch (InterruptedException e) {
+        Logging.error(e);
+      }
+      return;
+    }
+    this.ex = new ThreadPoolExecutor(20, 35, 25, TimeUnit.SECONDS,
+      new ArrayBlockingQueue<>(10));
+    for (StreetsideAbstractImage image : this.images) {
+      if (image instanceof StreetsideImage) {
+        try {
+          this.ex.execute(new StreetsideExportDownloadThread(
+              (StreetsideImage) image, this.queue, this.queueImages));
+        } catch (Exception e) {
+          Logging.error(e);
+        }
+      } else if (image instanceof StreetsideImportedImage) {
+        try {
+          this.queue.put(((StreetsideImportedImage) image).getImage());
+          this.queueImages.put(image);
+        } catch (InterruptedException e) {
+          Logging.error(e);
+        }
+      }
+      try {
+        // If the queue is full, waits for it to have more space
+        // available before executing anything else.
+        while (this.ex.getQueue().remainingCapacity() == 0) {
+          Thread.sleep(100);
+        }
+      } catch (Exception e) {
+        Logging.error(e);
+      }
+    }
+    try {
+      this.writer.join();
+    } catch (InterruptedException e) {
+      Logging.error(e);
+    }
+  }
+
+  @Override
+  protected void finish() {
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/StreetsideExportWriterThread.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/StreetsideExportWriterThread.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/StreetsideExportWriterThread.java	(revision 34317)
@@ -0,0 +1,152 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.io.export;
+
+import java.awt.image.BufferedImage;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.concurrent.ArrayBlockingQueue;
+
+import javax.imageio.ImageIO;
+
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.ImageWriteException;
+import org.apache.commons.imaging.Imaging;
+import org.apache.commons.imaging.common.ImageMetadata;
+import org.apache.commons.imaging.common.RationalNumber;
+import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
+import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
+import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
+import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;
+import org.apache.commons.imaging.formats.tiff.constants.GpsTagConstants;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputDirectory;
+import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
+
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.gui.progress.swing.PleaseWaitProgressMonitor;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImportedImage;
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+ * Writes the images from the queue in the file system.
+ *
+ * @author nokutu
+ * @see StreetsideExportManager
+ */
+public class StreetsideExportWriterThread extends Thread {
+
+  private final String path;
+  private final ArrayBlockingQueue<BufferedImage> queue;
+  private final ArrayBlockingQueue<StreetsideAbstractImage> queueImages;
+  private final int amount;
+  private final ProgressMonitor monitor;
+
+  /**
+   * Main constructor.
+   *
+   * @param path
+   *          Path to write the pictures.
+   * @param queue
+   *          Queue of {@link StreetsideAbstractImage} objects.
+   * @param queueImages
+   *          Queue of {@link BufferedImage} objects.
+   * @param amount
+   *          Amount of images that are going to be exported.
+   * @param monitor
+   *          Progress monitor.
+   */
+  public StreetsideExportWriterThread(String path,
+      ArrayBlockingQueue<BufferedImage> queue,
+      ArrayBlockingQueue<StreetsideAbstractImage> queueImages, int amount,
+      ProgressMonitor monitor) {
+    this.path = path;
+    this.queue = queue;
+    this.queueImages = queueImages;
+    this.amount = amount;
+    this.monitor = monitor;
+  }
+
+  @Override
+  public void run() {
+    monitor.setCustomText("Downloaded 0/" + amount);
+    BufferedImage img;
+    StreetsideAbstractImage mimg;
+    String finalPath = "";
+    for (int i = 0; i < amount; i++) {
+      try {
+        img = queue.take();
+        mimg = queueImages.take();
+        if (path == null && mimg instanceof StreetsideImportedImage) {
+          String path = ((StreetsideImportedImage) mimg).getFile().getPath();
+          finalPath = path.substring(0, path.lastIndexOf('.'));
+        } else if (mimg instanceof StreetsideImage) {
+          finalPath = path + '/' + ((StreetsideImage) mimg).getId();
+        } else if (mimg instanceof StreetsideImportedImage) {
+          finalPath = path + '/' + ((StreetsideImportedImage) mimg).getFile().getName();
+        }
+
+        // Transforms the image into a byte array.
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        ImageIO.write(img, "jpg", outputStream);
+        byte[] imageBytes = outputStream.toByteArray();
+
+        // Write EXIF tags
+        TiffOutputSet outputSet = null;
+        TiffOutputDirectory exifDirectory;
+        TiffOutputDirectory gpsDirectory;
+        // If the image is imported, loads the rest of the EXIF data.
+        if (mimg instanceof StreetsideImportedImage) {
+          final ImageMetadata metadata = Imaging
+              .getMetadata(((StreetsideImportedImage) mimg).getFile());
+          final JpegImageMetadata jpegMetadata = (JpegImageMetadata) metadata;
+          if (null != jpegMetadata) {
+            final TiffImageMetadata exif = jpegMetadata.getExif();
+            if (null != exif) {
+              outputSet = exif.getOutputSet();
+            }
+          }
+        }
+        if (null == outputSet) {
+          outputSet = new TiffOutputSet();
+        }
+        exifDirectory = outputSet.getOrCreateExifDirectory();
+        gpsDirectory = outputSet.getOrCreateGPSDirectory();
+
+        gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF);
+        gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF,
+            GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION_REF_VALUE_TRUE_NORTH);
+
+        gpsDirectory.removeField(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION);
+        gpsDirectory.add(GpsTagConstants.GPS_TAG_GPS_IMG_DIRECTION,
+            RationalNumber.valueOf(mimg.getMovingHe()));
+
+        exifDirectory.removeField(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL);
+        if (mimg instanceof StreetsideImportedImage) {
+          exifDirectory.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL,
+              mimg.getDate("yyyy/MM/dd HH:mm:ss"));
+        } else if (mimg instanceof StreetsideImage) {
+          exifDirectory.add(ExifTagConstants.EXIF_TAG_DATE_TIME_ORIGINAL,
+              mimg.getDate("yyyy/MM/dd HH/mm/ss"));
+        }
+        outputSet.setGPSInDegrees(mimg.getMovingLatLon().lon(), mimg.getMovingLatLon().lat());
+        OutputStream os = new BufferedOutputStream(new FileOutputStream(finalPath + ".jpg"));
+        new ExifRewriter().updateExifMetadataLossless(imageBytes, os, outputSet);
+
+        os.close();
+      } catch (InterruptedException e) {
+        Logging.info("Streetside export cancelled");
+        return;
+      } catch (IOException | ImageReadException | ImageWriteException e) {
+        Logging.error(e);
+      }
+
+      // Increases the progress bar.
+      monitor.worked(PleaseWaitProgressMonitor.PROGRESS_BAR_MAX / amount);
+      monitor.setCustomText("Downloaded " + (i + 1) + "/" + amount);
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/package-info.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/package-info.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/io/export/package-info.java	(revision 34317)
@@ -0,0 +1,5 @@
+// License: GPL. For details, see LICENSE file.
+/**
+ * Classes for exporting images that were downloaded from <a href="https://mapillary.com">mapillary.com</a> .
+ */
+package org.openstreetmap.josm.plugins.streetside.io.export;
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/mode/AbstractMode.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/mode/AbstractMode.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/mode/AbstractMode.java	(revision 34317)
@@ -0,0 +1,107 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.mode;
+
+import java.awt.Cursor;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.event.MouseAdapter;
+import java.util.Calendar;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.io.download.StreetsideDownloader;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.NavigatableComponent.ZoomChangeListener;
+
+/**
+ * Superclass for all the mode of the {@link StreetsideLayer}.
+ *
+ * @author nokutu
+ * @see StreetsideLayer
+ */
+public abstract class AbstractMode extends MouseAdapter implements
+  ZoomChangeListener {
+
+  private static final int DOWNLOAD_COOLDOWN = 2000;
+  private static SemiautomaticThread semiautomaticThread = new SemiautomaticThread();
+
+  /**
+   * Cursor that should become active when this mode is activated.
+   */
+  public int cursor = Cursor.DEFAULT_CURSOR;
+
+  protected StreetsideAbstractImage getClosest(Point clickPoint) {
+    double snapDistance = 10;
+    double minDistance = Double.MAX_VALUE;
+    StreetsideAbstractImage closest = null;
+    for (StreetsideAbstractImage image : StreetsideLayer.getInstance().getData().getImages()) {
+      Point imagePoint = MainApplication.getMap().mapView.getPoint(image.getMovingLatLon());
+      imagePoint.setLocation(imagePoint.getX(), imagePoint.getY());
+      double dist = clickPoint.distanceSq(imagePoint);
+      if (minDistance > dist && clickPoint.distance(imagePoint) < snapDistance
+        && image.isVisible()) {
+        minDistance = dist;
+        closest = image;
+      }
+    }
+    return closest;
+  }
+
+  /**
+   * Paint the dataset using the engine set.
+   *
+   * @param g {@link Graphics2D} used for painting
+   * @param mv The object that can translate GeoPoints to screen coordinates.
+   * @param box Area where painting is going to be performed
+   */
+  public abstract void paint(Graphics2D g, MapView mv, Bounds box);
+
+  @Override
+  public void zoomChanged() {
+    if (StreetsideDownloader.getMode() == StreetsideDownloader.DOWNLOAD_MODE.VISIBLE_AREA) {
+      if (!semiautomaticThread.isAlive())
+        semiautomaticThread.start();
+      semiautomaticThread.moved();
+    }
+  }
+
+  /**
+   * Resets the semiautomatic mode thread.
+   */
+  public static void resetThread() {
+    semiautomaticThread.interrupt();
+    semiautomaticThread = new SemiautomaticThread();
+  }
+
+  private static class SemiautomaticThread extends Thread {
+
+    /** If in semiautomatic mode, the last Epoch time when there was a download */
+    private long lastDownload;
+
+    private boolean moved;
+
+    @Override
+    public void run() {
+      while (true) {
+        if (this.moved && Calendar.getInstance().getTimeInMillis() - this.lastDownload >= DOWNLOAD_COOLDOWN) {
+          this.lastDownload = Calendar.getInstance().getTimeInMillis();
+          StreetsideDownloader.downloadVisibleArea();
+          this.moved = false;
+          StreetsideLayer.invalidateInstance();
+        }
+        try {
+          Thread.sleep(100);
+        } catch (InterruptedException e) {
+          return;
+        }
+      }
+    }
+
+    public void moved() {
+      this.moved = true;
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/mode/JoinMode.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/mode/JoinMode.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/mode/JoinMode.java	(revision 34317)
@@ -0,0 +1,94 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.mode;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.event.MouseEvent;
+import java.util.Arrays;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImportedImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.history.StreetsideRecord;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.plugins.streetside.history.commands.CommandJoin;
+import org.openstreetmap.josm.plugins.streetside.history.commands.CommandUnjoin;
+
+/**
+ * In this mode the user can join pictures to make sequences or unjoin them.
+ *
+ * @author nokutu
+ *
+ */
+public class JoinMode extends AbstractMode {
+
+  private StreetsideImportedImage lastClick;
+  private MouseEvent lastPos;
+
+  /**
+   * Main constructor.
+   */
+  public JoinMode() {
+    this.cursor = Cursor.CROSSHAIR_CURSOR;
+  }
+
+  @Override
+  public void mousePressed(MouseEvent e) {
+    final StreetsideAbstractImage highlighted = StreetsideLayer.getInstance().getData().getHighlightedImage();
+    if (highlighted == null) {
+      return;
+    }
+    if (this.lastClick == null && highlighted instanceof StreetsideImportedImage) {
+      this.lastClick = (StreetsideImportedImage) highlighted;
+    } else if (this.lastClick != null
+        && highlighted instanceof StreetsideImportedImage) {
+      if (
+        (
+          (highlighted.previous() == null && this.lastClick.next() == null) ||
+          (highlighted.next() == null && this.lastClick.previous() == null)
+        )
+        && highlighted.getSequence() != this.lastClick.getSequence()
+      ) {
+        StreetsideRecord.getInstance().addCommand(new CommandJoin(this.lastClick, highlighted));
+      } else if (this.lastClick.next() == highlighted || this.lastClick.previous() == highlighted) {
+        StreetsideRecord.getInstance().addCommand(
+          new CommandUnjoin(Arrays.asList(this.lastClick, highlighted))
+        );
+      }
+      this.lastClick = null;
+    }
+    StreetsideLayer.invalidateInstance();
+  }
+
+  @Override
+  public void mouseMoved(MouseEvent e) {
+    this.lastPos = e;
+    if (!(MainApplication.getLayerManager().getActiveLayer() instanceof StreetsideLayer))
+      return;
+    StreetsideAbstractImage closestTemp = getClosest(e.getPoint());
+    StreetsideLayer.getInstance().getData().setHighlightedImage(closestTemp);
+    StreetsideLayer.invalidateInstance();
+  }
+
+  @Override
+  public void paint(Graphics2D g, MapView mv, Bounds box) {
+    if (this.lastClick != null) {
+      g.setColor(Color.WHITE);
+      Point p0 = mv.getPoint(this.lastClick.getMovingLatLon());
+      Point p1 = this.lastPos.getPoint();
+      g.drawLine(p0.x, p0.y, p1.x, p1.y);
+    }
+  }
+
+  @Override
+  public String toString() {
+    return tr("Join mode");
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/mode/SelectMode.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/mode/SelectMode.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/mode/SelectMode.java	(revision 34317)
@@ -0,0 +1,196 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.mode;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+import javax.swing.SwingUtilities;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideData;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.gui.StreetsideMainDialog;
+import org.openstreetmap.josm.plugins.streetside.history.StreetsideRecord;
+import org.openstreetmap.josm.plugins.streetside.history.commands.CommandMove;
+import org.openstreetmap.josm.plugins.streetside.history.commands.CommandTurn;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+
+/**
+ * Handles the input event related with the layer. Mainly clicks.
+ *
+ * @author nokutu
+ */
+public class SelectMode extends AbstractMode {
+  private StreetsideAbstractImage closest;
+  private StreetsideAbstractImage lastClicked;
+  private final StreetsideRecord record;
+  private boolean nothingHighlighted;
+  private boolean imageHighlighted;
+
+  /**
+   * Main constructor.
+   */
+  public SelectMode() {
+    record = StreetsideRecord.getInstance();
+  }
+
+  @Override
+  public void mousePressed(MouseEvent e) {
+    if (e.getButton() != MouseEvent.BUTTON1) {
+      return;
+    }
+    StreetsideAbstractImage closest = getClosest(e.getPoint());
+    if (!(MainApplication.getLayerManager().getActiveLayer() instanceof StreetsideLayer)
+            && closest != null && MainApplication.getMap().mapMode == MainApplication.getMap().mapModeSelect) {
+      lastClicked = this.closest;
+      StreetsideLayer.getInstance().getData().setSelectedImage(closest);
+      return;
+    } else if (MainApplication.getLayerManager().getActiveLayer() != StreetsideLayer.getInstance()) {
+      return;
+    }
+    // Double click
+    if (e.getClickCount() == 2 && StreetsideLayer.getInstance().getData().getSelectedImage() != null && closest != null) {
+      closest.getSequence().getImages().forEach(StreetsideLayer.getInstance().getData()::addMultiSelectedImage);
+    }
+    lastClicked = this.closest;
+    this.closest = closest;
+    if (closest != null && StreetsideLayer.getInstance().getData().getMultiSelectedImages().contains(closest)) {
+      return;
+    }
+    // ctrl+click
+    if (e.getModifiers() == (InputEvent.BUTTON1_MASK | InputEvent.CTRL_MASK) && closest != null) {
+      StreetsideLayer.getInstance().getData().addMultiSelectedImage(closest);
+      // shift + click
+    } else if (
+            e.getModifiers() == (InputEvent.BUTTON1_MASK | InputEvent.SHIFT_MASK)
+                    && lastClicked instanceof StreetsideImage
+            ) {
+      if (this.closest != null
+              && this.closest.getSequence() == (lastClicked).getSequence()) {
+        int i = this.closest.getSequence().getImages().indexOf(this.closest);
+        int j = lastClicked.getSequence().getImages().indexOf(lastClicked);
+        StreetsideLayer.getInstance().getData().addMultiSelectedImage(
+                i < j
+                        ? new ConcurrentSkipListSet<>(this.closest.getSequence().getImages().subList(i, j + 1))
+                        : new ConcurrentSkipListSet<>(this.closest.getSequence().getImages().subList(j, i + 1))
+        );
+      }
+      // click
+    } else {
+      StreetsideLayer.getInstance().getData().setSelectedImage(closest);
+    }
+  }
+
+  @Override
+  public void mouseDragged(MouseEvent e) {
+    StreetsideAbstractImage highlightImg = StreetsideLayer.getInstance().getData().getHighlightedImage();
+    if (
+            MainApplication.getLayerManager().getActiveLayer() == StreetsideLayer.getInstance()
+                && SwingUtilities.isLeftMouseButton(e)
+                && highlightImg != null && highlightImg.getLatLon() != null
+            ) {
+      Point highlightImgPoint = MainApplication.getMap().mapView.getPoint(highlightImg.getTempLatLon());
+      if (e.isShiftDown()) { // turn
+        StreetsideLayer.getInstance().getData().getMultiSelectedImages().parallelStream().filter(img -> !(img instanceof StreetsideImage) || StreetsideProperties.DEVELOPER.get())
+                .forEach(img -> img.turn(Math.toDegrees(Math.atan2(e.getX() - highlightImgPoint.getX(), -e.getY() + highlightImgPoint.getY())) - highlightImg.getTempHe()));
+      } else { // move
+        LatLon eventLatLon = MainApplication.getMap().mapView.getLatLon(e.getX(), e.getY());
+        LatLon imgLatLon = MainApplication.getMap().mapView.getLatLon(highlightImgPoint.getX(), highlightImgPoint.getY());
+        StreetsideLayer.getInstance().getData().getMultiSelectedImages().parallelStream().filter(img -> !(img instanceof StreetsideImage) || StreetsideProperties.DEVELOPER.get())
+                .forEach(img -> img.move(eventLatLon.getX() - imgLatLon.getX(), eventLatLon.getY() - imgLatLon.getY()));
+      }
+      StreetsideLayer.invalidateInstance();
+    }
+  }
+
+  @Override
+  public void mouseReleased(MouseEvent e) {
+    final StreetsideData data = StreetsideLayer.getInstance().getData();
+    if (data.getSelectedImage() == null) {
+      return;
+    }
+    if (!Objects.equals(data.getSelectedImage().getTempHe(), data.getSelectedImage().getMovingHe())) {
+      double from = data.getSelectedImage().getTempHe();
+      double to = data.getSelectedImage().getMovingHe();
+      record.addCommand(new CommandTurn(data.getMultiSelectedImages(), to - from));
+    } else if (!Objects.equals(data.getSelectedImage().getTempLatLon(), data.getSelectedImage().getMovingLatLon())) {
+      LatLon from = data.getSelectedImage().getTempLatLon();
+      LatLon to = data.getSelectedImage().getMovingLatLon();
+      record.addCommand(new CommandMove(data.getMultiSelectedImages(), to.getX() - from.getX(), to.getY() - from.getY()));
+    }
+    data.getMultiSelectedImages().parallelStream().filter(Objects::nonNull).forEach(StreetsideAbstractImage::stopMoving);
+    StreetsideLayer.invalidateInstance();
+  }
+
+  /**
+   * Checks if the mouse is over pictures.
+   */
+  @Override
+  public void mouseMoved(MouseEvent e) {
+    if (MainApplication.getLayerManager().getActiveLayer() instanceof OsmDataLayer
+            && MainApplication.getMap().mapMode != MainApplication.getMap().mapModeSelect) {
+      return;
+    }
+    if (!StreetsideProperties.HOVER_ENABLED.get()) {
+      return;
+    }
+
+    StreetsideAbstractImage closestTemp = getClosest(e.getPoint());
+
+    final OsmDataLayer editLayer = MainApplication.getLayerManager().getEditLayer();
+    if (editLayer != null) {
+      if (closestTemp != null && !imageHighlighted) {
+        if (MainApplication.getMap().mapMode != null) {
+          MainApplication.getMap().mapMode.putValue("active", Boolean.FALSE);
+        }
+        imageHighlighted = true;
+      } else if (closestTemp == null && imageHighlighted && nothingHighlighted) {
+        if (MainApplication.getMap().mapMode != null) {
+          MainApplication.getMap().mapMode.putValue("active", Boolean.TRUE);
+        }
+        nothingHighlighted = false;
+      } else if (imageHighlighted && !nothingHighlighted && editLayer.data != null) {
+        for (OsmPrimitive primivitive : MainApplication.getLayerManager().getEditLayer().data.allPrimitives()) {
+          primivitive.setHighlighted(false);
+        }
+        imageHighlighted = false;
+        nothingHighlighted = true;
+      }
+    }
+
+    if (StreetsideLayer.getInstance().getData().getHighlightedImage() != closestTemp && closestTemp != null) {
+      StreetsideLayer.getInstance().getData().setHighlightedImage(closestTemp);
+      StreetsideMainDialog.getInstance().setImage(closestTemp);
+      StreetsideMainDialog.getInstance().updateImage(false);
+
+    } else if (StreetsideLayer.getInstance().getData().getHighlightedImage() != closestTemp && closestTemp == null) {
+      StreetsideLayer.getInstance().getData().setHighlightedImage(null);
+      StreetsideMainDialog.getInstance().setImage(StreetsideLayer.getInstance().getData().getSelectedImage());
+      StreetsideMainDialog.getInstance().updateImage();
+    }
+
+    StreetsideLayer.invalidateInstance();
+  }
+
+  @Override
+  public void paint(Graphics2D g, MapView mv, Bounds box) {
+  }
+
+  @Override
+  public String toString() {
+    return tr("Select mode");
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/mode/package-info.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/mode/package-info.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/mode/package-info.java	(revision 34317)
@@ -0,0 +1,11 @@
+// License: GPL. For details, see LICENSE file.
+/**
+ * The different modes that the {@link org.openstreetmap.josm.plugins.streetside.StreetsideLayer} can be in.
+ * <br>
+ * Currently there are two of them:
+ * <ul>
+ *  <li><strong>{@link org.openstreetmap.josm.plugins.mapillary.mode.JoinMode}</strong> for joining pictures to make sequences</li>
+ *  <li><strong>{@link org.openstreetmap.josm.plugins.mapillary.mode.SelectMode}</strong> for selecting pictures in the layer</li>
+ * </ul>
+ */
+package org.openstreetmap.josm.plugins.streetside.mode;
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/ImageDetection.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/ImageDetection.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/ImageDetection.java	(revision 34317)
@@ -0,0 +1,35 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.model;
+
+import java.awt.geom.Path2D;
+
+public class ImageDetection extends SpecialImageArea {
+  private static final String PACKAGE_TRAFFIC_SIGNS = "trafficsign";
+
+  private final String packag;
+  private final double score;
+  private final String value;
+
+  public ImageDetection(final Path2D shape, final String imageKey, final String key, final double score, final String packag, final String value) {
+    super(shape, imageKey, key);
+    this.packag = packag;
+    this.score = score;
+    this.value = value;
+  }
+
+  public String getPackage() {
+    return packag;
+  }
+
+  public double getScore() {
+    return score;
+  }
+
+  public String getValue() {
+    return value;
+  }
+
+  public boolean isTrafficSign() {
+    return PACKAGE_TRAFFIC_SIGNS.equals(packag);
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/KeyIndexedObject.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/KeyIndexedObject.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/KeyIndexedObject.java	(revision 34317)
@@ -0,0 +1,54 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.model;
+
+/**
+ * An object that is identified amongst objects of the same class by a {@link String} key.
+ */
+public class KeyIndexedObject {
+  private final String key;
+
+  protected KeyIndexedObject(final String key) {
+    if (key == null) {
+      throw new IllegalArgumentException();
+    }
+    this.key = key;
+  }
+
+  /**
+   * @return the unique key that identifies this object among other instances of the same class
+   */
+  public String getKey() {
+    return key;
+  }
+
+  /* (non-Javadoc)
+   * @see java.lang.Object#hashCode()
+   */
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    return prime * (prime + getClass().getName().hashCode()) + key.hashCode();
+  }
+
+  /* (non-Javadoc)
+   * @see java.lang.Object#equals(java.lang.Object)
+   */
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+    KeyIndexedObject other = (KeyIndexedObject) obj;
+    if (!key.equals(other.key)) {
+      return false;
+    }
+    return true;
+  }
+
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/MapObject.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/MapObject.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/MapObject.java	(revision 34317)
@@ -0,0 +1,89 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.model;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.function.Function;
+
+import javax.imageio.ImageIO;
+import javax.swing.ImageIcon;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.cache.Caches.MapObjectIconCache;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.MainWebsite;
+import org.openstreetmap.josm.tools.ImageProvider;
+import org.openstreetmap.josm.tools.Logging;
+
+public class MapObject extends KeyIndexedObject {
+  private static final ImageIcon ICON_UNKNOWN_TYPE = ImageProvider.get("unknown-mapobject-type");
+  private static Function<String, URL> iconUrlGen = MainWebsite::mapObjectIcon;
+
+  private final LatLon coordinate;
+  private final String objPackage;
+  private final String value;
+  private final long firstSeenTime;
+  private final long lastSeenTime;
+  private final long updatedTime;
+
+  public MapObject(
+    final LatLon coordinate, final String key, final String objPackage, final String value,
+    long firstSeenTime, long lastSeenTime, long updatedTime
+  ) {
+    super(key);
+    if (objPackage == null || value == null || coordinate == null) {
+      throw new IllegalArgumentException("The fields of a MapObject must not be null!");
+    }
+    this.coordinate = coordinate;
+    this.objPackage = objPackage;
+    this.value = value;
+    this.firstSeenTime = firstSeenTime;
+    this.lastSeenTime = lastSeenTime;
+    this.updatedTime = updatedTime;
+  }
+
+  public LatLon getCoordinate() {
+    return coordinate;
+  }
+
+  /**
+   * @param objectTypeID the {@link String} representing the type of map object. This ID can be retrieved via
+   *   {@link #getValue()} for any given {@link MapObject}.
+   * @return the icon, which represents the given objectTypeID
+   */
+  public static ImageIcon getIcon(final String objectTypeID) {
+    final ImageIcon cachedIcon = MapObjectIconCache.getInstance().get(objectTypeID);
+    if ("not-in-set".equals(objectTypeID)) {
+      return ICON_UNKNOWN_TYPE;
+    } else if (cachedIcon == null) {
+      try {
+        final ImageIcon downloadedIcon = new ImageIcon(ImageIO.read(iconUrlGen.apply(objectTypeID)));
+        MapObjectIconCache.getInstance().put(objectTypeID, downloadedIcon);
+        return downloadedIcon;
+      } catch (IOException e) {
+        Logging.log(Logging.LEVEL_WARN, "Failed to download icon " + objectTypeID, e);
+        return ICON_UNKNOWN_TYPE;
+      }
+    }
+    return cachedIcon;
+  }
+
+  public String getPackage() {
+    return objPackage;
+  }
+
+  public long getFirstSeenTime() {
+    return firstSeenTime;
+  }
+
+  public long getLastSeenTime() {
+    return lastSeenTime;
+  }
+
+  public long getUpdatedTime() {
+    return updatedTime;
+  }
+
+  public String getValue() {
+    return value;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/SpecialImageArea.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/SpecialImageArea.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/SpecialImageArea.java	(revision 34317)
@@ -0,0 +1,23 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.model;
+
+import java.awt.geom.Path2D;
+
+public class SpecialImageArea extends KeyIndexedObject {
+  private final String imageKey;
+  private final Path2D shape;
+
+  protected SpecialImageArea(final Path2D shape, final String imageKey, final String key) {
+    super(key);
+    this.shape = shape;
+    this.imageKey = imageKey;
+  }
+
+  public String getImageKey() {
+    return imageKey;
+  }
+
+  public Path2D getShape() {
+    return shape;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/UserProfile.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/UserProfile.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/model/UserProfile.java	(revision 34317)
@@ -0,0 +1,28 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.model;
+
+import java.io.Serializable;
+
+import javax.swing.ImageIcon;
+
+public class UserProfile extends KeyIndexedObject implements Serializable {
+  
+  private static final long serialVersionUID = 7993340649510343946L;
+  
+  private final String username;
+  private final ImageIcon avatar;
+
+  public UserProfile(String key, String username, ImageIcon avatar) {
+    super(key);
+    this.avatar = avatar;
+    this.username = username;
+  }
+
+  public String getUsername() {
+    return username;
+  }
+
+  public ImageIcon getAvatar() {
+    return avatar;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/OAuthPortListener.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/OAuthPortListener.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/OAuthPortListener.java	(revision 34317)
@@ -0,0 +1,93 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.oauth;
+
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.BindException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Scanner;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+* Listens to the OAuth port (8763) in order to get the access token and sends
+* back a simple reply.
+*
+* @author nokutu
+*
+*/
+public class OAuthPortListener extends Thread {
+public static final int PORT = 8763;
+
+protected static final String RESPONSE = String.format(
+   "<!DOCTYPE html><html><head><meta charset=\"utf8\"><title>%s</title></head><body>%s</body></html>",
+   I18n.tr("Mapillary login"),
+   I18n.tr("Login successful, return to JOSM.")
+);
+private final StreetsideLoginListener callback;
+
+public OAuthPortListener(StreetsideLoginListener loginCallback) {
+ this.callback = loginCallback;
+}
+
+@Override
+public void run() {
+ try (
+     ServerSocket serverSocket = new ServerSocket(PORT);
+     Socket clientSocket = serverSocket.accept();
+     PrintWriter out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream(), "UTF-8"), true);
+     Scanner in = new Scanner(new InputStreamReader(clientSocket.getInputStream(), "UTF-8"))
+ ) {
+   String s;
+   String accessToken = null;
+   while (in.hasNextLine()) {
+     s = in.nextLine();
+     Matcher tokenMatcher = Pattern.compile("^.*&access_token=([^&]+)&.*$").matcher('&'+s+'&');
+     if (tokenMatcher.matches()) {
+       accessToken = tokenMatcher.group(1);
+       break;
+     } else if (s.contains("keep-alive")) {
+       break;
+     }
+   }
+
+   writeContent(out);
+   out.flush();
+
+   StreetsideUser.reset();
+
+   Logging.info("Successful login with Mapillary, the access token is: {0}", accessToken);
+   // Saves the access token in preferences.
+   StreetsideUser.setTokenValid(true);
+   if (Main.main != null) {
+     StreetsideProperties.ACCESS_TOKEN.put(accessToken);
+     String username = StreetsideUser.getUsername();
+     Logging.info("The username is: {0}", username);
+     if (callback != null) {
+       callback.onLogin(username);
+     }
+   }
+ } catch (BindException e) {
+   Logging.warn(e);
+ } catch (IOException e) {
+   Logging.error(e);
+ }
+}
+
+private static void writeContent(PrintWriter out) {
+ out.println("HTTP/1.1 200 OK");
+ out.println("Content-Length: " + RESPONSE.length());
+ out.println("Content-Type: text/html" + "\r\n\r\n");
+ out.println(RESPONSE);
+}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/OAuthUtils.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/OAuthUtils.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/OAuthUtils.java	(revision 34317)
@@ -0,0 +1,52 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.oauth;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import javax.json.Json;
+import javax.json.JsonException;
+import javax.json.JsonObject;
+import javax.json.JsonReader;
+
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+
+/**
+* A set of utilities related to OAuth.
+*
+* @author nokutu
+*
+*/
+public final class OAuthUtils {
+
+private OAuthUtils() {
+ // Private constructor to avoid instantiation
+}
+
+/**
+* Returns a JsonObject containing the result of making a GET request with the
+* authorization header.
+*
+* @param url
+*          The {@link URL} where the request must be made.
+* @return A JsonObject containing the result of the GET request.
+* @throws IOException
+*           Errors relating to the connection.
+*/
+public static JsonObject getWithHeader(URL url) throws IOException {
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+ con.setRequestMethod("GET");
+ con.setRequestProperty("Authorization", "Bearer " + StreetsideProperties.ACCESS_TOKEN.get());
+
+ try (
+   JsonReader reader = Json.createReader(new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8")))
+ ) {
+   return reader.readObject();
+ } catch (JsonException e) {
+   throw new IOException(e);
+ }
+}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/StreetsideLoginListener.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/StreetsideLoginListener.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/StreetsideLoginListener.java	(revision 34317)
@@ -0,0 +1,21 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.oauth;
+
+/**
+ * This interface should be implemented by components that want to get notified when the user
+ * logs in or logs out of his Streetside account.
+ * Such listeners can be registered e.g. at a {@link OAuthPortListener}.
+ */
+public interface StreetsideLoginListener {
+  /**
+   * Should be called whenever the user logs into a mapillary account.
+   * E.g. for updating the GUI to reflect the login status.
+   * @param username the username that the user is now logged in with
+   */
+  void onLogin(final String username);
+  /**
+   * Should be called whenever the user logs out of a mapillary account.
+   * E.g. for updating the GUI to reflect the login status.
+   */
+  void onLogout();
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/StreetsideUser.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/StreetsideUser.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/oauth/StreetsideUser.java	(revision 34317)
@@ -0,0 +1,91 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.oauth;
+
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL;
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+* Represents the current logged in user and stores its data.
+*
+* @author nokutu
+*
+*/
+public final class StreetsideUser {
+
+private static String username;
+private static String imagesPolicy;
+private static String imagesHash;
+/** If the stored token is valid or not. */
+private static boolean isTokenValid = true;
+
+private StreetsideUser() {
+ // Private constructor to avoid instantiation
+}
+
+/**
+* @return The username of the logged in user.
+*/
+public static synchronized String getUsername() {
+ if (!isTokenValid) {
+   return null;
+ }
+ if (username == null) {
+   try {
+     username = OAuthUtils
+         .getWithHeader(StreetsideURL.APIv3.userURL())
+         .getString("username");
+   } catch (IOException e) {
+     Logging.log(Logging.LEVEL_WARN, "Invalid Streetside token, resetting field", e);
+     reset();
+   }
+ }
+ return username;
+}
+
+/**
+* @return A HashMap object containing the images_policy and images_hash
+*         strings.
+*/
+public static synchronized Map<String, String> getSecrets() {
+ if (!isTokenValid)
+   return null;
+ Map<String, String> hash = new HashMap<>();
+ try {
+   if (imagesHash == null)
+     imagesHash = OAuthUtils
+         .getWithHeader(StreetsideURL.uploadSecretsURL())
+         .getString("images_hash", null);
+   hash.put("images_hash", imagesHash);
+   if (imagesPolicy == null)
+     imagesPolicy = OAuthUtils
+         .getWithHeader(StreetsideURL.uploadSecretsURL())
+         .getString("images_policy");
+ } catch (IOException e) {
+   Logging.log(Logging.LEVEL_WARN, "Invalid Streetside token, resetting field", e);
+   reset();
+ }
+ hash.put("images_policy", imagesPolicy);
+ return hash;
+}
+
+/**
+* Resets the MapillaryUser to null values.
+*/
+public static synchronized void reset() {
+ username = null;
+ imagesPolicy = null;
+ imagesHash = null;
+ isTokenValid = false;
+ StreetsideProperties.ACCESS_TOKEN.put(StreetsideProperties.ACCESS_TOKEN.getDefaultValue());
+}
+
+public static synchronized void setTokenValid(boolean value) {
+ isTokenValid = value;
+}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/package-info.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/package-info.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/package-info.java	(revision 34317)
@@ -0,0 +1,5 @@
+// License: GPL. For details, see LICENSE file.
+/**
+ * The main package in which all core-code (so at the moment all code) resides.
+ */
+package org.openstreetmap.josm.plugins.streetside;
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/CubemapBox.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/CubemapBox.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/CubemapBox.java	(revision 34317)
@@ -0,0 +1,324 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import java.awt.image.BufferedImage;
+
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
+import org.openstreetmap.josm.plugins.streetside.cubemap.GraphicsUtils;
+
+import javafx.animation.AnimationTimer;
+import javafx.beans.property.DoubleProperty;
+import javafx.beans.property.SimpleDoubleProperty;
+import javafx.geometry.Rectangle2D;
+import javafx.scene.Group;
+import javafx.scene.PerspectiveCamera;
+import javafx.scene.image.Image;
+import javafx.scene.image.ImageView;
+import javafx.scene.transform.Affine;
+import javafx.scene.transform.Rotate;
+import javafx.scene.transform.Transform;
+
+/**
+ *
+ * @author Dub
+ * @author renerr18
+ */
+@SuppressWarnings("restriction")
+public  class CubemapBox extends Group{
+
+	public enum CubemapBoxImageType{
+        MULTIPLE, SINGLE
+    }
+
+    private final Affine affine = new Affine();
+
+    private final ImageView
+    front = new ImageView(),
+	right = new ImageView(),
+	back  = new ImageView(),
+	left  = new ImageView(),
+    up    = new ImageView(),
+    down  = new ImageView();
+
+    {
+    	front.setId(CubemapUtils.CubemapFaces.FRONT.getValue());
+    	right.setId(CubemapUtils.CubemapFaces.RIGHT.getValue());
+    	back.setId(CubemapUtils.CubemapFaces.BACK.getValue());
+    	left.setId(CubemapUtils.CubemapFaces.LEFT.getValue());
+    	up.setId(CubemapUtils.CubemapFaces.UP.getValue());
+        down .setId(CubemapUtils.CubemapFaces.DOWN.getValue());
+
+    }
+    private final ImageView[] views = new ImageView[]{
+    	front,
+    	right,
+    	back,
+    	left,
+    	up,
+        down
+    };
+
+	private Image
+		frontImg, rightImg, backImg, leftImg, upImg, downImg, singleImg;
+
+	//private WritableImage convertedImage;
+
+    private final PerspectiveCamera camera;
+    private AnimationTimer timer;
+    private final CubemapBoxImageType imageType;
+
+    public CubemapBox(Image singleImg, double size, PerspectiveCamera camera) {
+        super();
+        imageType = CubemapBoxImageType.SINGLE;
+
+        this.singleImg = singleImg;
+        this.size.set(size);
+        this.camera = camera;
+
+        getTransforms().add(affine);
+
+        loadImageViews();
+
+        getChildren().addAll(views);
+    }
+
+    // private constructor to prevent instantiation
+    public CubemapBox(double size, PerspectiveCamera camera) {
+        super();
+        imageType = CubemapBoxImageType.SINGLE;
+
+        this.size.set(size);
+        this.camera = camera;
+
+        getTransforms().add(affine);
+
+        loadImageViews();
+
+        getChildren().addAll(views);
+    }
+
+    public CubemapBox(Image frontImg, Image rightImg, Image backImg, Image leftImg, Image upImg, Image downImg, double size, PerspectiveCamera camera) {
+        super();
+        imageType = CubemapBoxImageType.MULTIPLE;
+
+        this.frontImg = frontImg;
+        this.rightImg = rightImg;
+        this.backImg = backImg;
+        this.leftImg = leftImg;
+        this.upImg = upImg;
+        this.downImg = downImg;
+        this.size.set(size);
+        this.camera = camera;
+
+        loadImageViews();
+
+        getTransforms().add(affine);
+
+        getChildren().addAll(views);
+
+        startTimer();
+    }
+
+    public void loadImageViews(){
+
+        for(ImageView iv : views){
+            iv.setSmooth(true);
+            iv.setPreserveRatio(true);
+        }
+
+        validateImageType();
+    }
+
+    private void layoutViews() {
+
+    	for(ImageView v : views){
+            v.setFitWidth(getSize());
+            v.setFitHeight(getSize());
+        }
+
+        back.setTranslateX(-0.5 * getSize());
+        back.setTranslateY(-0.5 * getSize());
+        back.setTranslateZ(-0.5 * getSize());
+
+        front.setTranslateX(-0.5 * getSize());
+        front.setTranslateY(-0.5 * getSize());
+        front.setTranslateZ(0.5 * getSize());
+        front.setRotationAxis(Rotate.Z_AXIS);
+        front.setRotate(-180);
+        front.getTransforms().add(new Rotate(180,front.getFitHeight() / 2, 0,0, Rotate.X_AXIS));
+        front.setTranslateY(front.getTranslateY() - getSize());
+
+        up.setTranslateX(-0.5 * getSize());
+        up.setTranslateY(-1 * getSize());
+        up.setRotationAxis(Rotate.X_AXIS);
+        up.setRotate(-90);
+
+        down.setTranslateX(-0.5 * getSize());
+        down.setTranslateY(0);
+        down.setRotationAxis(Rotate.X_AXIS);
+        down.setRotate(90);
+
+        left.setTranslateX(-1 * getSize());
+        left.setTranslateY(-0.5 * getSize());
+        left.setRotationAxis(Rotate.Y_AXIS);
+        left.setRotate(90);
+
+        right.setTranslateX(0);
+        right.setTranslateY(-0.5 * getSize());
+        right.setRotationAxis(Rotate.Y_AXIS);
+        right.setRotate(-90);
+
+    }
+    /**
+     *  for single image creates viewports and sets all views(image) to singleImg
+     *  for multiple... sets images per view.
+     */
+    private void validateImageType(){
+        switch(imageType){
+            case SINGLE:
+                loadSingleImageViewports();
+                break;
+            case MULTIPLE:
+                // TODO: implement single and double properly @rrh
+            	setMultipleImages();
+                break;
+        }
+    }
+    // TODO: change layout - Streetside cubemaps are structured as follows: @rrh
+    /**
+     * 01-front, 02-right, 03-back, 10-left, 11-up, 12-down
+     *
+     *         ____ ____ ____ ____ ____ ____
+     *        |fwd |rght|back|left|top |bot |
+     *        |____|____|____|____|____|____|
+     *
+     */
+
+    private void loadSingleImageViewports(){
+        layoutViews();
+        double width = singleImg.getWidth(),
+               height = singleImg.getHeight();
+
+        //simple check to see if cells will be square
+        if(width / 4 != height / 3){
+            throw new UnsupportedOperationException("Image does not comply with size constraints");
+        }
+        double cellSize = singleImg.getWidth() - singleImg.getHeight();
+
+        recalculateSize(cellSize);
+
+        double
+                topx = cellSize, topy = 0,
+
+                botx = cellSize, boty = cellSize * 2,
+
+                leftx = 0, lefty = cellSize,
+
+                rightx = cellSize * 2, righty = cellSize,
+
+                fwdx = cellSize, fwdy = cellSize,
+
+                backx = cellSize * 3, backy = cellSize;
+
+        //add top padding x+, y+, width-, height
+        up.setViewport(new Rectangle2D(topx , topy , cellSize, cellSize ));
+
+        //add left padding x, y+, width, height-
+        left.setViewport(new Rectangle2D(leftx , lefty , cellSize - 1, cellSize - 1));
+
+        //add front padding x+, y+, width-, height
+        front.setViewport(new Rectangle2D(fwdx , fwdy, cellSize , cellSize));
+
+        //add right padding x, y+, width, height-
+        right.setViewport(new Rectangle2D(rightx, righty , cellSize , cellSize ));
+
+        //add back padding x, y+, width, height-
+        back.setViewport(new Rectangle2D(backx + 1, backy - 1, cellSize - 1, cellSize - 1));
+
+        //add bottom padding x+, y, width-, height-
+        down.setViewport(new Rectangle2D(botx, boty, cellSize , cellSize));
+
+        for(ImageView v : views){
+            v.setImage(singleImg);
+        }
+    }
+
+
+
+    private void recalculateSize(double cell){
+        double factor = Math.floor(getSize() / cell);
+        setSize(cell * factor);
+    }
+
+	public synchronized void setImage(BufferedImage img, int position) {
+		views[position].setImage(GraphicsUtils.convertBufferedImage2JavaFXImage(img));
+
+	}
+
+
+    private void setMultipleImages() {
+		GraphicsUtils.PlatformHelper.run(() -> {
+			layoutViews();
+			front.setImage(frontImg);
+			right.setImage(rightImg);
+			back.setImage(backImg);
+			left.setImage(leftImg);
+			up.setImage(upImg);
+			down.setImage(downImg);
+
+		});
+	}
+
+    public void startTimer(){
+        timer = new AnimationTimer() {
+            @Override
+            public void handle(long now) {
+                Transform ct = (camera != null) ? camera.getLocalToSceneTransform() : null;
+                if(ct != null){
+                    affine.setTx(ct.getTx());
+                    affine.setTy(ct.getTy());
+                    affine.setTz(ct.getTz());
+                }
+            }
+        };
+        timer.start();
+    }
+
+    /*
+        Properties
+    */
+    private final DoubleProperty size = new SimpleDoubleProperty(){
+        @Override
+        protected void invalidated() {
+            switch(imageType){
+            case SINGLE:
+                layoutViews();
+                break;
+            case MULTIPLE:
+                break;
+            }
+
+        }
+    };
+
+    public final double getSize() {
+        return size.get();
+    }
+
+    public final void setSize(double value) {
+        size.set(value);
+    }
+
+    public DoubleProperty sizeProperty() {
+        return size;
+    }
+
+	public ImageView[] getViews() {
+		return views;
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/ImageUtil.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/ImageUtil.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/ImageUtil.java	(revision 34317)
@@ -0,0 +1,30 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import java.awt.Image;
+
+import javax.swing.ImageIcon;
+
+import org.openstreetmap.josm.tools.Logging;
+
+public final class ImageUtil {
+  private ImageUtil() {
+    // Private constructor to avoid instantiation
+  }
+
+  /**
+   * Scales an {@link ImageIcon} to the desired size
+   * @param icon the icon, which should be resized
+   * @param size the desired length of the longest edge of the icon
+   * @return the resized {@link ImageIcon}. It is the same object that you put in,
+   *         only the contained {@link Image} is exchanged.
+   */
+  public static ImageIcon scaleImageIcon(final ImageIcon icon, int size) {
+    Logging.debug("Scale icon {0} → {1}", icon.getIconWidth(), size);
+    return new ImageIcon(icon.getImage().getScaledInstance(
+      icon.getIconWidth() >= icon.getIconHeight() ? size : Math.max(1, Math.round(icon.getIconWidth() / (float) icon.getIconHeight() * size)),
+      icon.getIconHeight() >= icon.getIconWidth() ? size : Math.max(1, Math.round(icon.getIconHeight() / (float) icon.getIconWidth() * size)),
+      Image.SCALE_SMOOTH
+    ));
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/MapViewGeometryUtil.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/MapViewGeometryUtil.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/MapViewGeometryUtil.java	(revision 34317)
@@ -0,0 +1,69 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.geom.Area;
+import java.awt.geom.Path2D;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.NavigatableComponent;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideSequence;
+
+/**
+ * Utility class to convert entities like {@link Bounds} and {@link StreetsideSequence} into {@link Shape}s that
+ * can then easily be drawn on a {@link MapView}s {@link Graphics2D}-context.
+ */
+public final  class MapViewGeometryUtil {
+  private MapViewGeometryUtil() {
+    // Private constructor to avoid instantiation
+  }
+
+  /**
+   * Subtracts the download bounds from the rectangular bounds of the map view.
+   * @param mv the MapView that is used for the LatLon-to-Point-conversion and that determines
+   *     the Bounds from which the downloaded Bounds are subtracted
+   * @param downloadBounds multiple {@link Bounds} objects that represent the downloaded area
+   * @return the difference between the {@link MapView}s bounds and the downloaded area
+   */
+  public static Area getNonDownloadedArea(MapView mv, Iterable<Bounds> downloadBounds) {
+    Rectangle b = mv.getBounds();
+    // on some platforms viewport bounds seem to be offset from the left,
+    // over-grow it just to be sure
+    b.grow(100, 100);
+    Area a = new Area(b);
+    // now successively subtract downloaded areas
+    for (Bounds bounds : downloadBounds) {
+      Point p1 = mv.getPoint(bounds.getMin());
+      Point p2 = mv.getPoint(bounds.getMax());
+      Rectangle r = new Rectangle(Math.min(p1.x, p2.x), Math.min(p1.y, p2.y),
+          Math.abs(p2.x - p1.x), Math.abs(p2.y - p1.y));
+      a.subtract(new Area(r));
+    }
+    return a;
+  }
+
+  /**
+   * Converts a {@link StreetsideSequence} into a {@link Path2D} that can be drawn
+   * on the specified {@link NavigatableComponent}'s {@link Graphics2D}-context.
+   * @param nc the {@link NavigatableComponent} for which this conversion should be performed, typically a {@link MapView}
+   * @param seq the sequence to convert
+   * @return the {@link Path2D} object to which the {@link StreetsideSequence} has been converted
+   */
+  public static Path2D getSequencePath(NavigatableComponent nc, StreetsideSequence seq) {
+    final Path2D.Double path = new Path2D.Double();
+    seq.getImages().stream().filter(StreetsideAbstractImage::isVisible).forEach(img -> {
+      Point p = nc.getPoint(img.getMovingLatLon());
+      if (path.getCurrentPoint() == null) {
+        path.moveTo(p.getX(), p.getY());
+      } else {
+        path.lineTo(p.getX(), p.getY());
+      }
+    });
+    return path;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/PluginState.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/PluginState.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/PluginState.java	(revision 34317)
@@ -0,0 +1,140 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+ * @author nokutu
+ *
+ */
+public final class PluginState {
+
+  private static boolean submittingChangeset;
+
+  private static int runningDownloads;
+  /** Images that have to be uploaded. */
+  private static int imagesToUpload;
+  /** Images that have been uploaded. */
+  private static int imagesUploaded;
+
+  private PluginState() {
+    // Empty constructor to avoid instantiation
+  }
+
+  /**
+   * Called when a download is started.
+   */
+  public static void startDownload() {
+    runningDownloads++;
+  }
+
+  /**
+   * Called when a download is finished.
+   */
+  public static void finishDownload() {
+    if (runningDownloads == 0) {
+      Logging.warn("The amount of running downloads is equal to 0");
+      return;
+    }
+    runningDownloads--;
+  }
+
+  /**
+   * Checks if there is any running download.
+   *
+   * @return true if the plugin is downloading; false otherwise.
+   */
+  public static boolean isDownloading() {
+    return runningDownloads > 0;
+  }
+
+  /**
+   * Checks if there is a changeset being submitted.
+   *
+   * @return true if the plugin is submitting a changeset false otherwise.
+   */
+  public static boolean isSubmittingChangeset() {
+    return submittingChangeset;
+  }
+   /**
+   * Checks if there is any running upload.
+   *
+   * @return true if the plugin is uploading; false otherwise.
+   */
+  public static boolean isUploading() {
+    return imagesToUpload > imagesUploaded;
+  }
+
+  /**
+   * Sets the amount of images that are going to be uploaded.
+   *
+   * @param amount
+   *          The amount of images that are going to be uploaded.
+   */
+  public static void addImagesToUpload(int amount) {
+    if (imagesToUpload <= imagesUploaded) {
+      imagesToUpload = 0;
+      imagesUploaded = 0;
+    }
+    imagesToUpload += amount;
+  }
+
+  public static int getImagesToUpload() {
+    return imagesToUpload;
+  }
+
+  public static int getImagesUploaded() {
+    return imagesUploaded;
+  }
+
+  /**
+   * Called when an image is uploaded.
+   */
+  public static void imageUploaded() {
+    imagesUploaded++;
+    if (imagesToUpload == imagesUploaded && Main.main != null) {
+        finishedUploadDialog(imagesUploaded);
+    }
+  }
+
+  private static void finishedUploadDialog(int numImages) {
+    JOptionPane.showMessageDialog(
+      Main.parent,
+      tr("You have successfully uploaded {0} images to mapillary.com", numImages),
+      tr("Finished upload"),
+      JOptionPane.INFORMATION_MESSAGE
+    );
+  }
+
+  public static void notLoggedInToMapillaryDialog() {
+    if (Main.main == null) {
+      return;
+    }
+    JOptionPane.showMessageDialog(
+        Main.parent,
+        tr("You are not logged in, please log in to Mapillary in the preferences"),
+        tr("Not Logged in to Mapillary"),
+        JOptionPane.WARNING_MESSAGE
+    );
+  }
+
+
+
+  /**
+   * Returns the text to be written in the status bar.
+   *
+   * @return The {@code String} that is going to be written in the status bar.
+   */
+  public static String getUploadString() {
+    return tr("Uploading: {0}", "(" + imagesUploaded + "/" + imagesToUpload + ")");
+  }
+
+  public static void setSubmittingChangeset(boolean isSubmitting) {
+      submittingChangeset = isSubmitting;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideChangesetListener.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideChangesetListener.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideChangesetListener.java	(revision 34317)
@@ -0,0 +1,16 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideData;
+
+/**
+ * Interface for listeners of the class {@link StreetsideData}.
+ */
+@FunctionalInterface
+public interface StreetsideChangesetListener {
+
+  /**
+   * Fired when the an image is added or removed from the changeset.
+   */
+  void changesetChanged();
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideColorScheme.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideColorScheme.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideColorScheme.java	(revision 34317)
@@ -0,0 +1,63 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import java.awt.Color;
+
+import javax.swing.JComponent;
+
+public final class StreetsideColorScheme {
+  /**
+   * Color for unselected images
+   */
+  public static final Color SEQ_UNSELECTED = new Color(0x00ccd1);
+  /**
+   * Color for the camera angle indicator of images in unselected sequences
+   */
+  public static final Color SEQ_UNSELECTED_CA = new Color(0x4169e1);
+  /**
+   * Color for the marker of images in a selected sequence
+   */
+  public static final Color SEQ_SELECTED = new Color(0x00b5f5);
+  /**
+   * Color for the camera angle indicator of images in selected sequences
+   */
+  public static final Color SEQ_SELECTED_CA = new Color(0x8b008b);
+  /**
+   * Color for the marker of currently selected images
+   */
+  public static final Color SEQ_HIGHLIGHTED = new Color(0xf5811a);
+  /**
+   * Color for the camera angle indicator of the currently selected images
+   */
+  public static final Color SEQ_HIGHLIGHTED_CA = new Color(0xf5b81a);
+
+  public static final Color SEQ_IMPORTED_SELECTED = new Color(0xdddddd);
+  public static final Color SEQ_IMPORTED_SELECTED_CA = SEQ_IMPORTED_SELECTED.brighter();
+  public static final Color SEQ_IMPORTED_UNSELECTED = new Color(0x999999);
+  public static final Color SEQ_IMPORTED_UNSELECTED_CA = SEQ_IMPORTED_UNSELECTED.brighter();
+  public static final Color SEQ_IMPORTED_HIGHLIGHTED = new Color(0xbb2222);
+  public static final Color SEQ_IMPORTED_HIGHLIGHTED_CA = SEQ_IMPORTED_HIGHLIGHTED.brighter();
+
+  public static final Color STREETSIDE_BLUE = new Color(0x0000ff);
+  public static final Color TOOLBAR_DARK_GREY = new Color(0x242528);
+
+  public static final Color IMAGEDETECTION_TRAFFICSIGN = new Color(0xffc01b);
+  public static final Color IMAGEDETECTION_UNKNOWN = new Color(0x33bb44);
+
+  private StreetsideColorScheme() {
+    // Private constructor to avoid instantiation
+  }
+
+  /**
+   * Styles the given components as default panels (currently only the background is set to white)
+   * @param components the components to style as default panels (e.g. checkboxes also, that's why
+   *   not only JPanels are accepted)
+   */
+  public static void styleAsDefaultPanel(JComponent... components) {
+    if (components != null && components.length >= 1) {
+      for (JComponent component : components) {
+        component.setBackground(Color.WHITE);
+      }
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideProperties.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideProperties.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideProperties.java	(revision 34317)
@@ -0,0 +1,91 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import java.awt.Color;
+
+import org.openstreetmap.josm.data.preferences.BooleanProperty;
+import org.openstreetmap.josm.data.preferences.DoubleProperty;
+import org.openstreetmap.josm.data.preferences.IntegerProperty;
+import org.openstreetmap.josm.data.preferences.NamedColorProperty;
+import org.openstreetmap.josm.data.preferences.StringProperty;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.plugins.streetside.gui.imageinfo.ImageInfoPanel;
+import org.openstreetmap.josm.plugins.streetside.io.download.StreetsideDownloader;
+
+public final class StreetsideProperties {
+  public static final BooleanProperty DELETE_AFTER_UPLOAD = new BooleanProperty("streetside.delete-after-upload", true);
+  public static final BooleanProperty DEVELOPER = new BooleanProperty("streetside.developer", false);
+  public static final BooleanProperty DISPLAY_HOUR = new BooleanProperty("streetside.display-hour", true);
+  public static final BooleanProperty HOVER_ENABLED = new BooleanProperty("streetside.hover-enabled", true);
+  public static final BooleanProperty MOVE_TO_IMG = new BooleanProperty("streetside.move-to-picture", true);
+  public static final BooleanProperty TIME_FORMAT_24 = new BooleanProperty("streetside.format-24", false);
+  public static final BooleanProperty IMAGE_LINK_TO_BLUR_EDITOR = new BooleanProperty("streetside.image-link-to-blur-editor", true);
+  public static final BooleanProperty CUBEMAP_LINK_TO_BLUR_EDITOR = new BooleanProperty("streetside.cubemap-link-to-blur-editor", true);
+  public static final IntegerProperty TILE_DOWNLOAD_THREAD_PAUSE_LEN_SEC = new IntegerProperty("streetside.tile-download-thread-pause-len-sec", 60);
+  public static final BooleanProperty PREDOWNLOAD_CUBEMAPS = new BooleanProperty("streetside.predownload-cubemaps", true);
+
+  /**
+   * If false, all sequences that cross the download bounds are put completely into the StreetsideData object.
+   * Otherwise only all images (!) inside the download bounds are added, the others are discarded.
+   */
+  public static final BooleanProperty CUT_OFF_SEQUENCES_AT_BOUNDS =
+    new BooleanProperty("streetside.cut-off-sequences-at-bounds", false);
+  public static final IntegerProperty MAPOBJECT_ICON_SIZE = new IntegerProperty("streetside.mapobjects.iconsize", 32);
+  public static final IntegerProperty MAX_MAPOBJECTS = new IntegerProperty("streetside.mapobjects.maximum-number", 200);
+  public static final BooleanProperty SHOW_DETECTED_SIGNS = new BooleanProperty("streetside.show-detected-signs", true);
+  public static final BooleanProperty SHOW_HIGH_RES_STREETSIDE_IMAGERY = new BooleanProperty("streetside.show-high-res-streetside-imagery", true);
+
+  /**
+   * @see OsmDataLayer#PROPERTY_BACKGROUND_COLOR
+   */
+  public static final NamedColorProperty BACKGROUND = new NamedColorProperty("background", Color.BLACK);
+  /**
+   * @see OsmDataLayer#PROPERTY_OUTSIDE_COLOR
+   */
+  public static final NamedColorProperty OUTSIDE_DOWNLOADED_AREA = new NamedColorProperty("outside downloaded area", Color.YELLOW);
+
+  public static final DoubleProperty MAX_DOWNLOAD_AREA = new DoubleProperty("streetside.max-download-area", 0.015);
+
+  public static final IntegerProperty PICTURE_DRAG_BUTTON = new IntegerProperty("streetside.picture-drag-button", 3);
+  public static final IntegerProperty PICTURE_OPTION_BUTTON = new IntegerProperty("streetside.picture-option-button", 2);
+  public static final IntegerProperty PICTURE_ZOOM_BUTTON = new IntegerProperty("streetside.picture-zoom-button", 1);
+  public static final IntegerProperty SEQUENCE_MAX_JUMP_DISTANCE =
+    new IntegerProperty("streetside.sequence-max-jump-distance", 100);
+
+  public static final StringProperty ACCESS_TOKEN = new StringProperty("streetside.access-token", null);
+  public static final StringProperty DOWNLOAD_MODE =
+    new StringProperty("streetside.download-mode", StreetsideDownloader.DOWNLOAD_MODE.DEFAULT.getPrefId());
+  public static final StringProperty START_DIR =
+    new StringProperty("streetside.start-directory", System.getProperty("user.home"));
+
+  /**
+   * The number of times the help popup for the {@link ImageInfoPanel} will be displayed.
+   * But regardless of this number, the popup will only show up at most once between two (re)starts of JOSM.
+   * Or opening the {@link ImageInfoPanel} immediately brings this number down to zero.
+   */
+  public static final IntegerProperty IMAGEINFO_HELP_COUNTDOWN =
+    new IntegerProperty("streetside.imageInfo.helpDisplayedCountdown", 4);
+
+  /**
+   * The number of times the help popup for the {@link StreetsideViewerPanel} will be displayed.
+   * But regardless of this number, the popup will only show up at most once between two (re)starts of JOSM.
+   * Or opening the {@link StreetsideViewerPanel} immediately brings this number down to zero.
+   */
+  public static final IntegerProperty STREETSIDE_VIEWER_HELP_COUNTDOWN =
+    new IntegerProperty("streetside.streetsideViewer.helpDisplayedCountdown", 4);
+
+  /**
+   * The number of images to be prefetched when a streetside image is selected
+   */
+  public static final IntegerProperty PRE_FETCH_IMAGE_COUNT = new IntegerProperty("streetside.prefetch-image-count", 2);
+
+  /**
+   * The number of images to be prefetched when a streetside image is selected
+   */
+  public static final IntegerProperty PRE_FETCH_CUBEMAP_COUNT = new IntegerProperty("streetside.prefetch-image-count", 2);
+
+
+  private StreetsideProperties() {
+    // Private constructor to avoid instantiation
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideSequenceIdGenerator.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideSequenceIdGenerator.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideSequenceIdGenerator.java	(revision 34317)
@@ -0,0 +1,17 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import java.util.UUID;
+
+/**
+ * 
+ */
+public class StreetsideSequenceIdGenerator {
+  
+  public static String generateId() {
+    
+    return UUID.randomUUID().toString();
+    
+  }
+
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideURL.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideURL.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideURL.java	(revision 34317)
@@ -0,0 +1,374 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
+import org.openstreetmap.josm.tools.I18n;
+import org.openstreetmap.josm.tools.Logging;
+
+public final class StreetsideURL {
+	/** Base URL of the Bing Bubble API. */
+	private static final String STREETSIDE_BASE_URL = "https://dev.virtualearth.net/mapcontrol/HumanScaleServices/GetBubbles.ashx";
+	private static final String BASE_API_V2_URL = "https://a.mapillary.com/v2/";
+	private static final String CLIENT_ID = "T1Fzd20xZjdtR0s1VDk5OFNIOXpYdzoxNDYyOGRkYzUyYTFiMzgz";
+	private static final String BING_MAPS_KEY = "AuftgJsO0Xs8Ts4M1xZUQJQXJNsvmh3IV8DkNieCiy3tCwCUMq76-WpkrBtNAuEm";
+	private static final String TEST_BUBBLE_ID = "80848005";
+
+	private static final String STREETSIDE_PRIVACY_URL = "https://www.bing.com/maps/privacyreport/streetsideprivacyreport?bubbleid=";
+
+	private static final int OSM_BBOX_NORTH = 3;
+	private static final int OSM_BBOX_SOUTH = 1;
+	private static final int OSM_BBOXEAST = 2;
+	private static final int OSM_BBOX_WEST = 0;
+
+	public static final class APIv3 {
+		private static final String BASE_URL = "https://a.mapillary.com/v3/";
+
+		private APIv3() {
+			// Private constructor to avoid instantiation
+		}
+
+		public static URL getUser(String key) {
+			return StreetsideURL.string2URL(APIv3.BASE_URL, "users/", key, StreetsideURL.queryString(null));
+		}
+
+		/**
+		 * @return the URL where you can create, get and approve changesets
+		 */
+		public static URL submitChangeset() {
+			return StreetsideURL.string2URL(APIv3.BASE_URL, "changesets", APIv3.queryString(null));
+		}
+
+		public static URL searchDetections(Bounds bounds) {
+			return StreetsideURL.string2URL(APIv3.BASE_URL, "detections", APIv3.queryString(bounds));
+		}
+
+		public static URL searchImages(Bounds bounds) {
+			return StreetsideURL.string2URL(APIv3.BASE_URL, "images", APIv3.queryStreetsideString(bounds));
+		}
+
+		public static URL searchStreetsideImages(Bounds bounds) {
+			return StreetsideURL.string2URL(StreetsideURL.STREETSIDE_BASE_URL, APIv3.queryStreetsideString(bounds));
+		}
+
+		public static URL searchMapObjects(final Bounds bounds) {
+			return StreetsideURL.string2URL(APIv3.BASE_URL, "objects", APIv3.queryString(bounds));
+		}
+
+		public static URL searchStreetsideSequences(final Bounds bounds) {
+			return StreetsideURL.string2URL(StreetsideURL.STREETSIDE_BASE_URL, APIv3.queryStreetsideString(bounds));
+		}
+
+		/**
+		 * The APIv3 returns a Link header for each request. It contains a URL for requesting more results.
+		 * If you supply the value of the Link header, this method returns the next URL,
+		 * if such a URL is defined in the header.
+		 * @param value the value of the HTTP-header with key "Link"
+		 * @return the {@link URL} for the next result page, or <code>null</code> if no such URL could be found
+		 */
+		public static URL parseNextFromLinkHeaderValue(String value) {
+			if (value != null) {
+				// Iterate over the different entries of the Link header
+				for (final String link : value.split(",", Integer.MAX_VALUE)) {
+					boolean isNext = false;
+					URL url = null;
+					// Iterate over the parts of each entry (typically it's one `rel="‹linkType›"` and one like `<https://URL>`)
+					for (String linkPart : link.split(";", Integer.MAX_VALUE)) {
+						linkPart = linkPart.trim();
+						isNext |= linkPart.matches("rel\\s*=\\s*\"next\"");
+						if (linkPart.length() >= 1 && linkPart.charAt(0) == '<' && linkPart.endsWith(">")) {
+							try {
+								url = new URL(linkPart.substring(1, linkPart.length() - 1));
+							} catch (final MalformedURLException e) {
+								Logging.log(Logging.LEVEL_WARN, "Mapillary API v3 returns a malformed URL in the Link header.", e);
+							}
+						}
+					}
+					// If both a URL and the rel=next attribute are present, return the URL. Otherwise null is returned
+					if (url != null && isNext) {
+						return url;
+					}
+				}
+			}
+			return null;
+		}
+
+		public static String queryString(final Bounds bounds) {
+			if (bounds != null) {
+				final Map<String, String> parts = new HashMap<>();
+				parts.put("bbox", bounds.toBBox().toStringCSV(","));
+				return StreetsideURL.queryString(parts);
+			}
+			return StreetsideURL.queryString(null);
+		}
+
+		public static String queryStreetsideString(final Bounds bounds) {
+			if (bounds != null) {
+				final Map<String, String> parts = new HashMap<>();
+				parts.put("bbox", bounds.toBBox().toStringCSV(","));
+				return StreetsideURL.queryStreetsideBoundsString(parts);
+			}
+			return StreetsideURL.queryStreetsideBoundsString(null);
+		}
+
+		/**
+		 * @return the URL where you'll find information about the user account as JSON
+		 */
+		public static URL userURL() {
+			return StreetsideURL.string2URL(APIv3.BASE_URL, "me", StreetsideURL.queryString(null));
+		}
+	}
+
+	public static final class VirtualEarth {
+		private static final String BASE_URL_PREFIX = "https://t.ssl.ak.tiles.virtualearth.net/tiles/hs";
+		private static final String BASE_URL_SUFFIX = ".jpg?g=6338&n=z";
+
+		private VirtualEarth() {
+			// Private constructor to avoid instantiation
+		}
+
+		public static URL streetsideTile(String id, boolean thumbnail) {
+			if(thumbnail) {
+				id = id + "01";
+			}
+			URL url = StreetsideURL.string2URL(VirtualEarth.BASE_URL_PREFIX + id + VirtualEarth.BASE_URL_SUFFIX);
+			Logging.info("Tile task URL {0} invoked.", url.toString());
+			return url;
+		}
+	}
+
+	public static final class MainWebsite {
+		private static final String BASE_URL = "https://www.mapillary.com/";
+
+		private MainWebsite() {
+			// Private constructor to avoid instantiation
+		}
+
+		/**
+		 * Gives you the URL for the online viewer of a specific Streetside image.
+		 * @param id the id of the image to which you want to link
+		 * @return the URL of the online viewer for the image with the given image key
+		 * @throws IllegalArgumentException if the image key is <code>null</code>
+		 */
+		public static URL browseImage(String id) {
+			if (id == null) {
+				throw new IllegalArgumentException("The image key must not be null!");
+			}
+			return StreetsideURL.string2URL(VirtualEarth.BASE_URL_PREFIX + id + VirtualEarth.BASE_URL_SUFFIX);
+		}
+
+		/**
+		 * Gives you the URL for the blur editor of the image with the given key.
+		 * @param key the key of the image for which you want to open the blur editor
+		 * @return the URL of the blur editor
+		 * @throws IllegalArgumentException if the image key is <code>null</code>
+		 */
+		public static URL blurEditImage(final String key) {
+			if (key == null) {
+				throw new IllegalArgumentException("The image key must not be null!");
+			}
+			String urlEncodedKey;
+			try {
+				urlEncodedKey = URLEncoder.encode(key, StandardCharsets.UTF_8.name());
+			} catch (final UnsupportedEncodingException e) {
+				Logging.log(Logging.LEVEL_ERROR, "Unsupported encoding when URL encoding", e);
+				urlEncodedKey = key;
+			}
+			return StreetsideURL.string2URL(MainWebsite.BASE_URL, "app/blur?focus=photo&pKey=", urlEncodedKey);
+		}
+
+		/**
+		 * Gives you the URL for the blur editor of the image with the given key.
+		 * @param key the key of the image for which you want to open the blur editor
+		 * @return the URL of the blur editor
+		 * @throws IllegalArgumentException if the image key is <code>null</code>
+		 */
+		public static URL streetsidePrivacyLink(final String id) {
+			if (id == null) {
+				throw new IllegalArgumentException("The image id must not be null!");
+			}
+			String urlEncodedId;
+			try {
+				urlEncodedId = URLEncoder.encode(id, StandardCharsets.UTF_8.name());
+			} catch (final UnsupportedEncodingException e) {
+				Logging.log(Logging.LEVEL_ERROR, "Unsupported encoding when URL encoding", e);
+				urlEncodedId = id;
+			}
+			return StreetsideURL.string2URL(StreetsideURL.STREETSIDE_PRIVACY_URL, urlEncodedId);
+		}
+
+		/**
+		 * Gives you the URL which the user should visit to initiate the OAuth authentication process
+		 * @param redirectURI the URI to which the user will be redirected when the authentication is finished.
+		 *        When this is <code>null</code>, it's omitted from the query string.
+		 * @return the URL that the user should visit to start the OAuth authentication
+		 */
+		public static URL connect(String redirectURI) {
+			final HashMap<String, String> parts = new HashMap<>();
+			if (redirectURI != null && redirectURI.length() >= 1) {
+				parts.put("redirect_uri", redirectURI);
+			}
+			parts.put("response_type", "token");
+			parts.put("scope", "user:read public:upload public:write");
+			return StreetsideURL.string2URL(MainWebsite.BASE_URL, "connect", StreetsideURL.queryString(parts));
+		}
+
+		public static URL mapObjectIcon(String key) {
+			return StreetsideURL.string2URL(MainWebsite.BASE_URL, "developer/api-documentation/images/traffic_sign/" + key + ".png");
+		}
+	}
+
+	private StreetsideURL() {
+		// Private constructor to avoid instantiation
+	}
+
+	public static URL[] string2URLs(String baseUrlPrefix, String cubemapImageId, String baseUrlSuffix) {
+		List<URL> res = new ArrayList<>();
+
+		switch (StreetsideProperties.SHOW_HIGH_RES_STREETSIDE_IMAGERY.get() ? 16 : 4) {
+
+		case 16:
+
+			EnumSet.allOf(CubemapUtils.CubemapFaces.class).forEach(face -> {
+				for (int i = 0; i < 4; i++) {
+					for (int j = 0; j < 4; j++) {
+						try {
+							final String urlStr = baseUrlPrefix + cubemapImageId
+									+ CubemapUtils.rowCol2StreetsideCellAddressMap
+											.get(String.valueOf(i) + String.valueOf(j))
+									+ baseUrlSuffix;
+							res.add(new URL(urlStr));
+						} catch (final MalformedURLException e) {
+							Logging.error(I18n.tr("Error creating URL String for cubemap {0}", cubemapImageId));
+							e.printStackTrace();
+						}
+
+					}
+				}
+			});
+
+		case 4:
+			EnumSet.allOf(CubemapUtils.CubemapFaces.class).forEach(face -> {
+				for (int i = 0; i < 4; i++) {
+
+					try {
+						final String urlStr = baseUrlPrefix + cubemapImageId
+								+ CubemapUtils.rowCol2StreetsideCellAddressMap.get(String.valueOf(i)) + baseUrlSuffix;
+						res.add(new URL(urlStr));
+					} catch (final MalformedURLException e) {
+						Logging.error(I18n.tr("Error creating URL String for cubemap {0}", cubemapImageId));
+						e.printStackTrace();
+					}
+
+				}
+			});
+			break; // break is optional
+		default:
+			// Statements
+		}
+		return res.stream().toArray(URL[]::new);
+	}
+
+	/**
+	 * @return the URL where you'll find the upload secrets as JSON
+	 */
+	public static URL uploadSecretsURL() {
+		return StreetsideURL.string2URL(StreetsideURL.BASE_API_V2_URL, "me/uploads/secrets", StreetsideURL.queryString(null));
+	}
+
+	/**
+	 * Builds a query string from it's parts that are supplied as a {@link Map}
+	 * @param parts the parts of the query string
+	 * @return the constructed query string (including a leading ?)
+	 */
+	static String queryString(Map<String, String> parts) {
+		final StringBuilder ret = new StringBuilder("?client_id=").append(StreetsideURL.CLIENT_ID);
+		if (parts != null) {
+			for (final Entry<String, String> entry : parts.entrySet()) {
+				try {
+					ret.append('&')
+					.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8.name()))
+					.append('=')
+					.append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.name()));
+				} catch (final UnsupportedEncodingException e) {
+					Logging.error(e); // This should not happen, as the encoding is hard-coded
+				}
+			}
+		}
+		return ret.toString();
+	}
+
+	static String queryStreetsideBoundsString(Map<String, String> parts) {
+		final StringBuilder ret = new StringBuilder("?n=");
+		if (parts != null) {
+			final List<String> bbox = new ArrayList<>(Arrays.asList(parts.get("bbox").split(",")));
+			try {
+				ret.append(URLEncoder.encode(bbox.get(StreetsideURL.OSM_BBOX_NORTH), StandardCharsets.UTF_8.name()))
+				.append("&s=")
+				.append(URLEncoder.encode(bbox.get(StreetsideURL.OSM_BBOX_SOUTH), StandardCharsets.UTF_8.name()))
+				.append("&e=")
+				.append(URLEncoder.encode(bbox.get(StreetsideURL.OSM_BBOXEAST), StandardCharsets.UTF_8.name()))
+				.append("&w=")
+				.append(URLEncoder.encode(bbox.get(StreetsideURL.OSM_BBOX_WEST), StandardCharsets.UTF_8.name()))
+				.append("&c=1000")
+				.append("&appkey=")
+				.append(StreetsideURL.BING_MAPS_KEY);
+			} catch (final UnsupportedEncodingException e) {
+				Logging.error(e); // This should not happen, as the encoding is hard-coded
+			}
+		}
+		return ret.toString();
+	}
+
+	/**
+	 *
+	 */
+	static String queryByIdString(Map<String, String> parts) {
+		final StringBuilder ret = new StringBuilder("?id=");
+		try {
+			ret.append(URLEncoder.encode(StreetsideURL.TEST_BUBBLE_ID, StandardCharsets.UTF_8.name()));
+			ret.append('&').append(URLEncoder.encode("appkey=", StandardCharsets.UTF_8.name())).append('=')
+			.append(URLEncoder.encode(StreetsideURL.BING_MAPS_KEY, StandardCharsets.UTF_8.name()));
+		} catch (final UnsupportedEncodingException e) {
+			Logging.error(e); // This should not happen, as the encoding is hard-coded
+		}
+		return ret.toString();
+	}
+
+	/**
+	 * Converts a {@link String} into a {@link URL} without throwing a {@link MalformedURLException}.
+	 * Instead such an exception will lead to an {@link Logging#error(Throwable)}.
+	 * So you should be very confident that your URL is well-formed when calling this method.
+	 * @param strings the Strings describing the URL
+	 * @return the URL that is constructed from the given string
+	 */
+	static URL string2URL(String... strings) {
+		final StringBuilder builder = new StringBuilder();
+		for (int i = 0; strings != null && i < strings.length; i++) {
+			builder.append(strings[i]);
+		}
+		try {
+			return new URL(builder.toString());
+		} catch (final MalformedURLException e) {
+			Logging.log(Logging.LEVEL_ERROR, String.format(
+					"The class '%s' produces malformed URLs like '%s'!",
+					StreetsideURL.class.getName(),
+					builder
+					), e);
+			return null;
+		}
+	}
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideUtils.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideUtils.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/StreetsideUtils.java	(revision 34317)
@@ -0,0 +1,285 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import java.awt.Desktop;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Locale;
+import java.util.Set;
+
+import javax.swing.SwingUtilities;
+
+import org.apache.commons.imaging.common.RationalNumber;
+import org.apache.commons.imaging.formats.tiff.constants.GpsTagConstants;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.StreetsideSequence;
+import org.openstreetmap.josm.tools.I18n;
+
+/**
+ * Set of utilities.
+ *
+ * @author nokutu
+ */
+public final class StreetsideUtils {
+
+  private static final double MIN_ZOOM_SQUARE_SIDE = 0.002;
+
+  private StreetsideUtils() {
+    // Private constructor to avoid instantiation
+  }
+
+  /**
+   * Open the default browser in the given URL.
+   *
+   * @param url The (not-null) URL that is going to be opened.
+   * @throws IOException when the URL could not be opened
+   */
+  public static void browse(URL url) throws IOException {
+    if (url == null) {
+      throw new IllegalArgumentException();
+    }
+    Desktop desktop = Desktop.getDesktop();
+    if (desktop.isSupported(Desktop.Action.BROWSE)) {
+      try {
+        desktop.browse(url.toURI());
+      } catch (URISyntaxException e1) {
+        throw new IOException(e1);
+      }
+    } else {
+      Runtime runtime = Runtime.getRuntime();
+      runtime.exec("xdg-open " + url);
+    }
+  }
+
+  /**
+   * Returns the current date formatted as EXIF timestamp.
+   * As timezone the default timezone of the JVM is used ({@link java.util.TimeZone#getDefault()}).
+   *
+   * @return A {@code String} object containing the current date.
+   */
+  public static String currentDate() {
+    return new SimpleDateFormat("yyyy:MM:dd HH:mm:ss", Locale.UK).format(Calendar.getInstance().getTime());
+  }
+
+  /**
+   * Returns current time in Epoch format (milliseconds since 1970-01-01T00:00:00+0000)
+   *
+   * @return The current date in Epoch format.
+   */
+  public static long currentTime() {
+    return Calendar.getInstance().getTimeInMillis();
+  }
+
+  /**
+   * Parses a string with a given format and returns the Epoch time.
+   * If no timezone information is given, the default timezone of the JVM is used
+   * ({@link java.util.TimeZone#getDefault()}).
+   *
+   * @param date   The string containing the date.
+   * @param format The format of the date.
+   * @return The date in Epoch format.
+   * @throws ParseException if the date cannot be parsed with the given format
+   */
+  public static long getEpoch(String date, String format) throws ParseException {
+    return new SimpleDateFormat(format, Locale.UK).parse(date).getTime();
+  }
+
+  /**
+   * Calculates the decimal degree-value from a degree value given in
+   * degrees-minutes-seconds-format
+   *
+   * @param degMinSec an array of length 3, the values in there are (in this order)
+   *                  degrees, minutes and seconds
+   * @param ref       the latitude or longitude reference determining if the given value
+   *                  is:
+   *                  <ul>
+   *                  <li>north (
+   *                  {@link GpsTagConstants#GPS_TAG_GPS_LATITUDE_REF_VALUE_NORTH}) or
+   *                  south (
+   *                  {@link GpsTagConstants#GPS_TAG_GPS_LATITUDE_REF_VALUE_SOUTH}) of
+   *                  the equator</li>
+   *                  <li>east (
+   *                  {@link GpsTagConstants#GPS_TAG_GPS_LONGITUDE_REF_VALUE_EAST}) or
+   *                  west ({@link GpsTagConstants#GPS_TAG_GPS_LONGITUDE_REF_VALUE_WEST}
+   *                  ) of the equator</li>
+   *                  </ul>
+   * @return the decimal degree-value for the given input, negative when west of
+   * 0-meridian or south of equator, positive otherwise
+   * @throws IllegalArgumentException if {@code degMinSec} doesn't have length 3 or if {@code ref} is
+   *                                  not one of the values mentioned above
+   */
+  public static double degMinSecToDouble(RationalNumber[] degMinSec, String ref) {
+    if (degMinSec == null || degMinSec.length != 3) {
+      throw new IllegalArgumentException("Array's length must be 3.");
+    }
+    for (int i = 0; i < 3; i++) {
+      if (degMinSec[i] == null)
+        throw new IllegalArgumentException("Null value in array.");
+    }
+
+    switch (ref) {
+      case GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF_VALUE_NORTH:
+      case GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF_VALUE_SOUTH:
+      case GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF_VALUE_EAST:
+      case GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF_VALUE_WEST:
+        break;
+      default:
+        throw new IllegalArgumentException("Invalid ref.");
+    }
+
+    double result = degMinSec[0].doubleValue(); // degrees
+    result += degMinSec[1].doubleValue() / 60; // minutes
+    result += degMinSec[2].doubleValue() / 3600; // seconds
+
+    if (GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF_VALUE_SOUTH.equals(ref)
+            || GpsTagConstants.GPS_TAG_GPS_LONGITUDE_REF_VALUE_WEST.equals(ref)) {
+      result *= -1;
+    }
+
+    result = 360 * ((result + 180) / 360 - Math.floor((result + 180) / 360)) - 180;
+    return result;
+  }
+
+  /**
+   * Joins two images into the same sequence. One of them must be the last image of a sequence, the other one the beginning of a different one.
+   *
+   * @param imgA the first image, into whose sequence the images from the sequence of the second image are merged
+   * @param imgB the second image, whose sequence is merged into the sequence of the first image
+   */
+  public static synchronized void join(StreetsideAbstractImage imgA, StreetsideAbstractImage imgB) {
+    if (imgA == null || imgB == null) {
+      throw new IllegalArgumentException("Both images must be non-null for joining.");
+    }
+    if (imgA.getSequence() == imgB.getSequence()) {
+      throw new IllegalArgumentException("You can only join images of different sequences.");
+    }
+    if ((imgA.next() != null || imgB.previous() != null) && (imgB.next() != null || imgA.previous() != null)) {
+      throw new IllegalArgumentException("You can only join an image at the end of a sequence with one at the beginning of another sequence.");
+    }
+    if (imgA.next() != null || imgB.previous() != null) {
+      join(imgB, imgA);
+    } else {
+      for (StreetsideAbstractImage img : imgB.getSequence().getImages()) {
+        imgA.getSequence().add(img);
+      }
+      StreetsideLayer.invalidateInstance();
+    }
+  }
+
+  /**
+   * Zooms to fit all the {@link StreetsideAbstractImage} objects stored in the
+   * database.
+   */
+  public static void showAllPictures() {
+    showPictures(StreetsideLayer.getInstance().getData().getImages(), false);
+  }
+
+  /**
+   * Zooms to fit all the given {@link StreetsideAbstractImage} objects.
+   *
+   * @param images The images your are zooming to.
+   * @param select Whether the added images must be selected or not.
+   */
+  public static void showPictures(final Set<StreetsideAbstractImage> images, final boolean select) {
+    if (!SwingUtilities.isEventDispatchThread()) {
+      SwingUtilities.invokeLater(() -> showPictures(images, select));
+    } else {
+      Bounds zoomBounds;
+      if (images.isEmpty()) {
+        zoomBounds = new Bounds(new LatLon(0, 0));
+      } else {
+        zoomBounds = new Bounds(images.iterator().next().getMovingLatLon());
+        for (StreetsideAbstractImage img : images) {
+          zoomBounds.extend(img.getMovingLatLon());
+        }
+      }
+
+      // The zoom rectangle must have a minimum size.
+      double latExtent = Math.max(zoomBounds.getMaxLat() - zoomBounds.getMinLat(), MIN_ZOOM_SQUARE_SIDE);
+      double lonExtent = Math.max(zoomBounds.getMaxLon() - zoomBounds.getMinLon(), MIN_ZOOM_SQUARE_SIDE);
+      zoomBounds = new Bounds(zoomBounds.getCenter(), latExtent, lonExtent);
+
+      MainApplication.getMap().mapView.zoomTo(zoomBounds);
+      StreetsideLayer.getInstance().getData().setSelectedImage(null);
+      if (select) {
+        StreetsideLayer.getInstance().getData().addMultiSelectedImage(images);
+      }
+      StreetsideLayer.invalidateInstance();
+    }
+
+  }
+
+  /**
+   * Separates two images belonging to the same sequence. The two images have to be consecutive in the same sequence.
+   * Two new sequences are created and all images up to (and including) either {@code imgA} or {@code imgB} (whichever appears first in the sequence) are put into the first of the two sequences.
+   * All others are put into the second new sequence.
+   *
+   * @param imgA one of the images marking where to split the sequence
+   * @param imgB the other image marking where to split the sequence, needs to be a direct neighbour of {@code imgA} in the sequence.
+   */
+  public static synchronized void unjoin(StreetsideAbstractImage imgA, StreetsideAbstractImage imgB) {
+    if (imgA == null || imgB == null) {
+      throw new IllegalArgumentException("Both images must be non-null for unjoining.");
+    }
+    if (imgA.getSequence() != imgB.getSequence()) {
+      throw new IllegalArgumentException("You can only unjoin with two images from the same sequence.");
+    }
+    if (imgB.equals(imgA.next()) && imgA.equals(imgB.next())) {
+      throw new IllegalArgumentException("When unjoining with two images these must be consecutive in one sequence.");
+    }
+
+    if (imgA.equals(imgB.next())) {
+      unjoin(imgB, imgA);
+    } else {
+      StreetsideSequence seqA = new StreetsideSequence();
+      StreetsideSequence seqB = new StreetsideSequence();
+      boolean insideFirstHalf = true;
+      for (StreetsideAbstractImage img : imgA.getSequence().getImages()) {
+        if (insideFirstHalf) {
+          seqA.add(img);
+        } else {
+          seqB.add(img);
+        }
+        if (img.equals(imgA)) {
+          insideFirstHalf = false;
+        }
+      }
+      StreetsideLayer.invalidateInstance();
+    }
+  }
+
+  /**
+   * Updates the help text at the bottom of the window.
+   */
+  public static void updateHelpText() {
+    if (MainApplication.getMap() == null || MainApplication.getMap().statusLine == null) {
+      return;
+    }
+    StringBuilder ret = new StringBuilder();
+    if (PluginState.isDownloading()) {
+      ret.append(I18n.tr("Downloading Streetside images"));
+    } else if (StreetsideLayer.hasInstance() && !StreetsideLayer.getInstance().getData().getImages().isEmpty()) {
+      ret.append(I18n.tr("Total Streetside images: {0}", StreetsideLayer.getInstance().getToolTipText()));
+    } else if (PluginState.isSubmittingChangeset()) {
+        ret.append(I18n.tr("Submitting Streetside Changeset"));
+    } else {
+      ret.append(I18n.tr("No images found"));
+    }
+    if (StreetsideLayer.hasInstance() && StreetsideLayer.getInstance().mode != null) {
+      ret.append(" — ").append(I18n.tr(StreetsideLayer.getInstance().mode.toString()));
+    }
+    if (PluginState.isUploading()) {
+      ret.append(" — ").append(PluginState.getUploadString());
+    }
+    MainApplication.getMap().statusLine.setHelpText(ret.toString());
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonDecoder.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonDecoder.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonDecoder.java	(revision 34317)
@@ -0,0 +1,110 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils.api;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.function.Function;
+
+import javax.json.JsonArray;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.tools.Logging;
+
+public final class JsonDecoder {
+  private JsonDecoder() {
+    // Private constructor to avoid instantiation
+  }
+
+  /**
+   * Parses a given {@link JsonObject} as a GeoJSON FeatureCollection into a {@link Collection}
+   * of the desired Java objects. The method, which converts the GeoJSON features into Java objects
+   * is given as a parameter to this method.
+   * @param <T> feature type
+   * @param json the {@link JsonObject} to be parsed
+   * @param featureDecoder feature decoder which transforms JSON objects to Java objects
+   * @return a {@link Collection} which is parsed from the given {@link JsonObject}, which contains GeoJSON.
+   *         Currently a {@link HashSet} is used, but please don't rely on it, this could change at any time without
+   *         prior notice. The return value will not be <code>null</code>.
+   */
+  public static <T> Collection<T> decodeFeatureCollection(final JsonObject json, Function<JsonObject, T> featureDecoder) {
+    final Collection<T> result = new HashSet<>();
+    if (
+      json != null && "FeatureCollection".equals(json.getString("type", null)) && json.containsKey("features")
+    ) {
+      final JsonValue features = json.get("features");
+      for (int i = 0; features instanceof JsonArray && i < ((JsonArray) features).size(); i++) {
+        final JsonValue val = ((JsonArray) features).get(i);
+        if (val instanceof JsonObject) {
+          final T feature = featureDecoder.apply((JsonObject) val);
+          if (feature != null) {
+            result.add(feature);
+          }
+        }
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Decodes a {@link JsonArray} of exactly size 2 to a {@link LatLon} instance.
+   * The first value in the {@link JsonArray} is treated as longitude, the second one as latitude.
+   * @param json the {@link JsonArray} containing the two numbers
+   * @return the decoded {@link LatLon} instance, or <code>null</code> if the parameter is
+   *         not a {@link JsonArray} of exactly size 2 containing two {@link JsonNumber}s.
+   */
+  static LatLon decodeLatLon(final JsonArray json) {
+    final double[] result = decodeDoublePair(json);
+    if (result != null) {
+      return new LatLon(result[1], result[0]);
+    }
+    return null;
+  }
+
+  /**
+   * Decodes a pair of double values, which are stored in a {@link JsonArray} of exactly size 2.
+   * @param json the {@link JsonArray} containing the two values
+   * @return a double array which contains the two values in the same order, or <code>null</code>
+   *         if the parameter was not a {@link JsonArray} of exactly size 2 containing two {@link JsonNumber}s
+   */
+  @SuppressWarnings("PMD.ReturnEmptyArrayRatherThanNull")
+  static double[] decodeDoublePair(final JsonArray json) {
+    if (
+      json != null &&
+      json.size() == 2 &&
+      json.get(0) instanceof JsonNumber &&
+      json.get(1) instanceof JsonNumber
+    ) {
+      return new double[]{json.getJsonNumber(0).doubleValue(), json.getJsonNumber(1).doubleValue()};
+    }
+    return null;
+  }
+
+  /**
+   * Decodes a timestamp formatted as a {@link String} to the equivalent UNIX epoch timestamp
+   * (number of milliseconds since 1970-01-01T00:00:00.000+0000).
+   * @param timestamp the timestamp formatted according to the format <code>yyyy-MM-dd'T'HH:mm:ss.SSSX</code>
+   * @return the point in time as a {@link Long} value representing the UNIX epoch time, or <code>null</code> if the
+   *   parameter does not match the required format (this also triggers a warning via
+   *   {@link Logging#warn(Throwable)}), or the parameter is <code>null</code>.
+   */
+  static Long decodeTimestamp(final String timestamp) {
+    if (timestamp != null) {
+      try {
+        return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.UK).parse(timestamp).getTime();
+      } catch (ParseException e) {
+        StackTraceElement calledBy = e.getStackTrace()[Math.min(e.getStackTrace().length - 1, 2)];
+        Logging.log(Logging.LEVEL_WARN,String.format(
+          "Could not decode time from the timestamp `%s` (called by %s.%s:%d)",
+          timestamp, calledBy.getClassName(), calledBy.getMethodName(), calledBy.getLineNumber()
+        ), e);
+      }
+    }
+    return null;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonImageDetailsDecoder.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonImageDetailsDecoder.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonImageDetailsDecoder.java	(revision 34317)
@@ -0,0 +1,45 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils.api;
+
+
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideData;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3;
+
+
+/**
+ * Decodes the JSON returned by {@link APIv3} into Java objects.
+ * Takes a {@link JsonObject} and {@link #decodeImageInfos(JsonObject, StreetsideData)} tries to add the timestamps.
+ */
+public final class JsonImageDetailsDecoder {
+  private JsonImageDetailsDecoder() {
+    // Private constructor to avoid instantiation
+  }
+
+  public static void decodeImageInfos(final JsonObject json, final StreetsideData data) {
+    if (data != null) {
+      JsonDecoder.decodeFeatureCollection(json, j -> {
+        decodeImageInfo(j, data);
+        return null;
+      });
+    }
+  }
+
+  private static void decodeImageInfo(final JsonObject json, final StreetsideData data) {
+    if (json != null && data != null) {
+      JsonValue properties = json.get("properties");
+      if (properties instanceof JsonObject) {
+        String id = ((JsonObject) properties).getString("id", null);
+        Long he = JsonDecoder.decodeTimestamp(((JsonObject)properties).getString("he", null));
+        if (id != null && he != null) {
+          data.getImages().stream().filter(
+            img -> img instanceof StreetsideImage && id.equals(((StreetsideImage) img).getId())
+          ).forEach(img -> img.setHe(he));
+        }
+      }
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonImageDetectionDecoder.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonImageDetectionDecoder.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonImageDetectionDecoder.java	(revision 34317)
@@ -0,0 +1,106 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils.api;
+
+import java.awt.Shape;
+import java.awt.geom.Path2D;
+
+import javax.json.JsonArray;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+
+import org.openstreetmap.josm.plugins.streetside.model.ImageDetection;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3;
+import org.openstreetmap.josm.tools.Logging;
+
+
+/**
+ * Decodes the JSON returned by {@link APIv3} into Java objects.
+ * Takes a {@link JsonObject} and {@link #decodeImageDetection(JsonObject)} tries to convert it to a {@link ImageDetection}.
+ */
+public final class JsonImageDetectionDecoder {
+  private JsonImageDetectionDecoder() {
+    // Private constructor to avoid instantiation
+  }
+
+  // TODO: Image detections? Keep? @rrh
+  public static ImageDetection decodeImageDetection(final JsonObject json) {
+    if (json == null || !"Feature".equals(json.getString("type", null))) {
+      return null;
+    }
+
+    final JsonValue properties = json.get("properties");
+    if (properties instanceof JsonObject) {
+      final String key = ((JsonObject) properties).getString("key", null);
+      final String packag = ((JsonObject) properties).getString("package", null);
+      final String imageKey = ((JsonObject) properties).getString("image_key", null);
+      final String value = ((JsonObject) properties).getString("value", null);
+      final JsonValue scoreVal = ((JsonObject) properties).get("score");
+      final Double score = scoreVal instanceof JsonNumber ? ((JsonNumber) scoreVal).doubleValue() : null;
+      final Shape shape = decodeShape(((JsonObject) properties).get("shape"));
+      if (shape instanceof Path2D && imageKey != null && key != null && score != null && packag != null && value != null) {
+        return new ImageDetection((Path2D) shape, imageKey, key, score, packag, value);
+      }
+    }
+    return null;
+  }
+
+  private static Shape decodeShape(JsonValue json) {
+    if (json instanceof JsonObject) {
+      if (!"Polygon".equals(((JsonObject) json).getString("type", null))) {
+        Logging.warn(
+          String.format("Image detections using shapes with type=%s are currently not supported!",
+          ((JsonObject) json).getString("type", "‹no type set›"))
+        );
+      } else {
+        final JsonValue coordinates = ((JsonObject) json).get("coordinates");
+        if (coordinates instanceof JsonArray && !((JsonArray) coordinates).isEmpty()) {
+          return decodePolygon((JsonArray) coordinates);
+        }
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Decodes a polygon (may be a multipolygon) from JSON
+   * @param json the json array to decode, must not be <code>null</code>
+   * @return the decoded polygon as {@link Path2D.Double}
+   */
+  private static Path2D decodePolygon(final JsonArray json) {
+    final Path2D shape = new Path2D.Double();
+    json.forEach(val -> {
+      final Shape part = val instanceof JsonArray ? decodeSimplePolygon((JsonArray) val) : null;
+      if (part != null) {
+        shape.append(part, false);
+      }
+    });
+    if (shape.getCurrentPoint() != null) {
+      return shape;
+    }
+    return null;
+  }
+
+  /**
+   * Decodes a simple polygon (consisting of only one continuous path) from JSON
+   * @param json the json array to decode, must not be <code>null</code>
+   * @return the decoded polygon as {@link Path2D.Double}
+   * @throws NullPointerException if parameter is <code>null</code>
+   */
+  private static Path2D decodeSimplePolygon(final JsonArray json) {
+    final Path2D shape = new Path2D.Double();
+    json.forEach(val -> {
+      double[] coord = JsonDecoder.decodeDoublePair(val instanceof JsonArray ? (JsonArray) val : null);
+      if (shape.getCurrentPoint() == null && coord != null) {
+        shape.moveTo(coord[0], coord[1]);
+      } else if (coord != null) {
+        shape.lineTo(coord[0], coord[1]);
+      }
+    });
+    if (shape.getCurrentPoint() != null) {
+      shape.closePath();
+      return shape;
+    }
+    return null;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonLocationChangesetEncoder.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonLocationChangesetEncoder.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonLocationChangesetEncoder.java	(revision 34317)
@@ -0,0 +1,57 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils.api;
+
+import java.util.Objects;
+
+import javax.json.Json;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObjectBuilder;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+
+import org.openstreetmap.josm.plugins.streetside.StreetsideLocationChangeset;
+
+
+public final class JsonLocationChangesetEncoder {
+  private JsonLocationChangesetEncoder() {
+    // Private constructor to avoid instantiation
+  }
+
+  public static JsonObjectBuilder encodeLocationChangeset(StreetsideLocationChangeset changeset) {
+    Objects.requireNonNull(changeset);
+    final JsonArrayBuilder imgChanges = Json.createArrayBuilder();
+    for (StreetsideImage img : changeset) {
+      imgChanges.add(encodeImageChanges(img));
+    }
+    return Json.createObjectBuilder()
+      .add("type", "location")
+      .add("changes", imgChanges)
+      .add("request_comment", "JOSM-created");
+  }
+
+  private static JsonObjectBuilder encodeImageChanges(StreetsideImage img) {
+    Objects.requireNonNull(img);
+
+    final JsonObjectBuilder to = Json.createObjectBuilder();
+    if (!img.getTempLatLon().equalsEpsilon(img.getLatLon())) {
+      to.add("geometry", Json.createObjectBuilder()
+        .add("coordinates", Json.createArrayBuilder()
+          .add(img.getTempLatLon().getX())
+          .add(img.getTempLatLon().getY())
+        ).add("type", "Point")
+      );
+    }
+    if (Math.abs(img.getHe() - img.getTempHe()) > 1e-9) {
+      to.add("properties", Json.createObjectBuilder().add("ca", img.getTempHe()));
+    } else {
+      to.add("properties", Json.createObjectBuilder());
+    }
+    if (!img.getTempLatLon().equalsEpsilon(img.getLatLon())) {
+      to.add("type", "Feature");
+    }
+
+    return Json.createObjectBuilder()
+      .add("image_key", img.getId())
+      .add("to", to);
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonMapObjectDecoder.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonMapObjectDecoder.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonMapObjectDecoder.java	(revision 34317)
@@ -0,0 +1,61 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils.api;
+
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.model.MapObject;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3;
+
+/**
+ * Decodes the JSON returned by {@link APIv3} into Java objects.
+ * Takes a {@link JsonObject} and {@link #decodeMapObject(JsonObject)} tries to convert it to a {@link MapObject}.
+ */
+public final class JsonMapObjectDecoder {
+  private JsonMapObjectDecoder() {
+    // Private constructor to avoid instantiation
+  }
+
+  public static MapObject decodeMapObject(final JsonObject json) {
+    if (json == null || !"Feature".equals(json.getString("type", null))) {
+      return null;
+    }
+
+    final JsonValue properties = json.get("properties");
+    final JsonValue geometry = json.get("geometry");
+    if (properties instanceof JsonObject && geometry instanceof JsonObject) {
+      final String key = ((JsonObject) properties).getString("key", null);
+      final String packg = ((JsonObject) properties).getString("package", null);
+      final String value = ((JsonObject) properties).getString("value", null);
+      final Long firstSeenTime = JsonDecoder.decodeTimestamp(((JsonObject) properties).getString("first_seen_at", null));
+      final Long lastSeenTime = JsonDecoder.decodeTimestamp(((JsonObject) properties).getString("last_seen_at", null));
+      final Long updatedTime = JsonDecoder.decodeTimestamp(((JsonObject) properties).getString("updated_at", null));
+
+      final JsonValue coordVal = "Point".equals(((JsonObject) geometry).getString("type", null))
+        ? ((JsonObject) geometry).get("coordinates")
+        : null;
+      final LatLon coordinate = coordVal instanceof JsonArray ? JsonDecoder.decodeLatLon((JsonArray) coordVal) : null;
+
+      if (
+        key != null &&
+        packg != null &&
+        value != null &&
+        firstSeenTime != null &&
+        lastSeenTime != null &&
+        updatedTime != null &&
+        coordinate != null
+      ) {
+        return new MapObject(
+          coordinate,
+          key,
+          packg,
+          value,
+          firstSeenTime, lastSeenTime, updatedTime
+        );
+      }
+    }
+    return null;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonSequencesDecoder.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonSequencesDecoder.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonSequencesDecoder.java	(revision 34317)
@@ -0,0 +1,137 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils.api;
+
+import java.lang.reflect.Array;
+import java.util.function.Function;
+
+import javax.json.JsonArray;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideSequence;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3;
+
+/**
+ * Decodes the JSON returned by {@link APIv3} into Java objects.
+ * Takes a {@link JsonObject} and {@link #decodeSequence(JsonObject)} tries to convert it to a {@link StreetsideSequence}.
+ */
+public final class JsonSequencesDecoder {
+  private JsonSequencesDecoder() {
+    // Private constructor to avoid instantiation
+  }
+
+  /**
+   * Parses a given {@link JsonObject} as a GeoJSON Feature into a {@link StreetsideSequence}.
+   * @param json the {@link JsonObject} to be parsed
+   * @return a {@link Streetsideequence} that is parsed from the given {@link JsonObject}. If mandatory information is
+   *         missing from the JSON or it's not meeting the expecting format in another way, <code>null</code> will be
+   *         returned.
+   */
+  public static StreetsideSequence decodeSequence(final JsonObject json) {
+    if (json == null || !"Feature".equals(json.getString("type", null))) {
+      return null;
+    }
+    StreetsideSequence result = null;
+    final JsonObject properties = json.getJsonObject("properties");
+    final Long ca = properties == null ? null : JsonDecoder.decodeTimestamp(properties.getString("cd", null));
+    if (properties != null && properties.getString("id", null) != null && properties.getString("user_key", null) != null && ca != null) {
+      result = new StreetsideSequence(properties.getString("id", null), ca);
+
+      final Double[] hes = decodeCoordinateProperty(
+        properties,
+        "hes",
+        val ->  val instanceof JsonNumber ? ((JsonNumber) val).doubleValue() : null,
+        Double.class
+      );
+      final String[] imageIds = decodeCoordinateProperty(
+        properties,
+        "image_ids",
+        val -> val instanceof JsonString ? ((JsonString) val).getString() : null,
+        String.class
+      );
+      final LatLon[] geometry = decodeLatLons(json.getJsonObject("geometry"));
+      final int sequenceLength = Math.min(Math.min(hes.length, imageIds.length), geometry.length);
+      for (int i = 0; i < sequenceLength; i++) {
+        if (hes[i] != null && imageIds[i] != null && geometry[i] != null) {
+          final StreetsideImage img = new StreetsideImage(imageIds[i], geometry[i], hes[i]);
+          result.add(img);
+        }
+      }
+      if (result.getImages().isEmpty()) {
+        result = null;
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Converts a {@link JsonArray} to a java array.
+   * The conversion from {@link JsonValue} to a java type is done by the supplied function.
+   * @param array the array to be converted
+   * @param decodeValueFunction the function used for conversion from {@link JsonValue} to the desired type.
+   * @param clazz the desired type that the elements of the resulting array should have
+   * @return the supplied array converted from {@link JsonArray} to a java array of the supplied type, converted using
+   *         the supplied function. Never <code>null</code>, in case of array==null, an array of length 0 is returned.
+   */
+  @SuppressWarnings("unchecked")
+  private static <T> T[] decodeJsonArray(final JsonArray array, final Function<JsonValue, T> decodeValueFunction, final Class<T> clazz) {
+    final T[] result;
+    if (array == null) {
+      result =  (T[]) Array.newInstance(clazz, 0);
+    } else {
+      result = (T[]) Array.newInstance(clazz, array.size());
+      for (int i = 0; i < result.length; i++) {
+        result[i] = decodeValueFunction.apply(array.get(i));
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Given the JSON object representing the `properties` of a sequence, this method converts you one attribute from the
+   * `coordinateProperties` object to an array of appropriate type.
+   *
+   * For example this is used to convert the `image_keys` JSON array to a String[] array or the `cas` JSON array to a
+   * Double[] array.
+   * @param json the JSON object representing the `properties` of a sequence
+   * @param key the key, which identifies the desired array inside the `coordinateProperties` object to be converted
+   * @param decodeValueFunction a function that converts the {@link JsonValue}s in the JSON array to java objects of the
+   *        desired type
+   * @param clazz the {@link Class} object of the desired type, that the entries of the resulting array should have
+   * @return the resulting array, when converting the desired entry of the `coordinateProperties`.
+   *         Never <code>null</code>. If no `coordinateProperties` are set, or if the desired key is not set or is not
+   *         an array, then an empty array of the desired type is returned.
+   */
+  @SuppressWarnings("unchecked")
+  private static <T> T[] decodeCoordinateProperty(
+    final JsonObject json, final String key, final Function<JsonValue, T> decodeValueFunction, final Class<T> clazz
+  ) {
+    final JsonValue coordinateProperties = json == null ? null : json.get("coordinateProperties");
+    if (coordinateProperties instanceof JsonObject) {
+      JsonValue valueArray = ((JsonObject) coordinateProperties).get(key);
+      if (valueArray instanceof JsonArray) {
+        return decodeJsonArray((JsonArray) valueArray, decodeValueFunction, clazz);
+      }
+    }
+    return (T[]) Array.newInstance(clazz, 0);
+  }
+
+  private static LatLon[] decodeLatLons(final JsonObject json) {
+    final JsonValue coords = json == null ? null : json.get("coordinates");
+    if (coords instanceof JsonArray && "LineString".equals(json.getString("type", null))) {
+      final LatLon[] result = new LatLon[((JsonArray) coords).size()];
+      for (int i = 0; i < ((JsonArray) coords).size(); i++) {
+        final JsonValue coord = ((JsonArray) coords).get(i);
+        if (coord instanceof JsonArray) {
+          result[i] = JsonDecoder.decodeLatLon((JsonArray) coord);
+        }
+      }
+      return result;
+    }
+    return new LatLon[0];
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonStreetsideDecoder.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonStreetsideDecoder.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonStreetsideDecoder.java	(revision 34317)
@@ -0,0 +1,110 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils.api;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.function.Function;
+
+import javax.json.JsonArray;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.tools.Logging;
+
+public final class JsonStreetsideDecoder {
+  private JsonStreetsideDecoder() {
+    // Private constructor to avoid instantiation
+  }
+
+  /**
+   * Parses a given {@link JsonObject} as a GeoJSON FeatureCollection into a {@link Collection}
+   * of the desired Java objects. The method, which converts the GeoJSON features into Java objects
+   * is given as a parameter to this method.
+   * @param <T> feature type
+   * @param json the {@link JsonObject} to be parsed
+   * @param featureDecoder feature decoder which transforms JSON objects to Java objects
+   * @return a {@link Collection} which is parsed from the given {@link JsonObject}, which contains GeoJSON.
+   *         Currently a {@link HashSet} is used, but please don't rely on it, this could change at any time without
+   *         prior notice. The return value will not be <code>null</code>.
+   */
+  public static <T> Collection<T> decodeFeatureCollection(final JsonObject json, Function<JsonObject, T> featureDecoder) {
+    final Collection<T> result = new HashSet<>();
+    if (
+      json != null && "FeatureCollection".equals(json.getString("type", null)) && json.containsKey("features")
+    ) {
+      final JsonValue features = json.get("features");
+      for (int i = 0; features instanceof JsonArray && i < ((JsonArray) features).size(); i++) {
+        final JsonValue val = ((JsonArray) features).get(i);
+        if (val instanceof JsonObject) {
+          final T feature = featureDecoder.apply((JsonObject) val);
+          if (feature != null) {
+            result.add(feature);
+          }
+        }
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Decodes a {@link JsonArray} of exactly size 2 to a {@link LatLon} instance.
+   * The first value in the {@link JsonArray} is treated as longitude, the second one as latitude.
+   * @param json the {@link JsonArray} containing the two numbers
+   * @return the decoded {@link LatLon} instance, or <code>null</code> if the parameter is
+   *         not a {@link JsonArray} of exactly size 2 containing two {@link JsonNumber}s.
+   */
+  static LatLon decodeLatLon(final JsonArray json) {
+    final double[] result = decodeDoublePair(json);
+    if (result != null) {
+      return new LatLon(result[1], result[0]);
+    }
+    return null;
+  }
+
+  /**
+   * Decodes a pair of double values, which are stored in a {@link JsonArray} of exactly size 2.
+   * @param json the {@link JsonArray} containing the two values
+   * @return a double array which contains the two values in the same order, or <code>null</code>
+   *         if the parameter was not a {@link JsonArray} of exactly size 2 containing two {@link JsonNumber}s
+   */
+  @SuppressWarnings("PMD.ReturnEmptyArrayRatherThanNull")
+  static double[] decodeDoublePair(final JsonArray json) {
+    if (
+      json != null &&
+      json.size() == 2 &&
+      json.get(0) instanceof JsonNumber &&
+      json.get(1) instanceof JsonNumber
+    ) {
+      return new double[]{json.getJsonNumber(0).doubleValue(), json.getJsonNumber(1).doubleValue()};
+    }
+    return null;
+  }
+
+  /**
+   * Decodes a timestamp formatted as a {@link String} to the equivalent UNIX epoch timestamp
+   * (number of milliseconds since 1970-01-01T00:00:00.000+0000).
+   * @param timestamp the timestamp formatted according to the format <code>yyyy-MM-dd'T'HH:mm:ss.SSSX</code>
+   * @return the point in time as a {@link Long} value representing the UNIX epoch time, or <code>null</code> if the
+   *   parameter does not match the required format (this also triggers a warning via
+   *   {@link Logging#warn(Throwable)}), or the parameter is <code>null</code>.
+   */
+  static Long decodeTimestamp(final String timestamp) {
+    if (timestamp != null) {
+      try {
+        return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX", Locale.UK).parse(timestamp).getTime();
+      } catch (ParseException e) {
+        StackTraceElement calledBy = e.getStackTrace()[Math.min(e.getStackTrace().length - 1, 2)];
+        Logging.log(Logging.LEVEL_WARN,String.format(
+          "Could not decode time from the timestamp `%s` (called by %s.%s:%d)",
+          timestamp, calledBy.getClassName(), calledBy.getMethodName(), calledBy.getLineNumber()
+        ), e);
+      }
+    }
+    return null;
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonStreetsideSequencesDecoder.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonStreetsideSequencesDecoder.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/api/JsonStreetsideSequencesDecoder.java	(revision 34317)
@@ -0,0 +1,188 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils.api;
+
+import java.lang.reflect.Array;
+import java.util.function.Function;
+
+import javax.json.JsonArray;
+import javax.json.JsonNumber;
+import javax.json.JsonObject;
+import javax.json.JsonString;
+import javax.json.JsonValue;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideSequence;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideURL.APIv3;
+
+/**
+ * Decodes the JSON returned by {@link APIv3} into Java objects.
+ * Takes a {@link JsonObject} and {@link #decodeSequence(JsonObject)} tries to convert it to a {@link StreetsideSequence}.
+ */
+public final class JsonStreetsideSequencesDecoder {
+  private JsonStreetsideSequencesDecoder() {
+    // Private constructor to avoid instantiation
+  }
+
+  /**
+   * Parses a given {@link JsonObject} as a GeoJSON Feature into a {@link StreetsideSequence}.
+   * @param json the {@link JsonObject} to be parsed
+   * @return a {@link StreetsideSequence} that is parsed from the given {@link JsonObject}. If mandatory information is
+   *         missing from the JSON or it's not meeting the expecting format in another way, <code>null</code> will be
+   *         returned.
+   */
+  public static StreetsideSequence decodeSequence(final JsonObject json) {
+    if (json == null || !"Feature".equals(json.getString("type", null))) {
+      return null;
+    }
+    StreetsideSequence result = null;
+    final JsonObject properties = json.getJsonObject("properties");
+    final Long ca = properties == null ? null : JsonDecoder.decodeTimestamp(properties.getString("cd", null));
+    if (properties != null && properties.getString("id", null) != null && ca != null) {
+      result = new StreetsideSequence(properties.getString("id", null), ca);
+
+      final Double[] cas = decodeCoordinateProperty(
+        properties,
+        "hes",
+        val ->  val instanceof JsonNumber ? ((JsonNumber) val).doubleValue() : null,
+        Double.class
+      );
+      final String[] imageIds = decodeCoordinateProperty(
+        properties,
+        "image_ids",
+        val -> val instanceof JsonString ? ((JsonString) val).getString() : null,
+        String.class
+      );
+      final LatLon[] geometry = decodeLatLons(json.getJsonObject("geometry"));
+      final int sequenceLength = Math.min(Math.min(cas.length, imageIds.length), geometry.length);
+      for (int i = 0; i < sequenceLength; i++) {
+        if (cas[i] != null && imageIds[i] != null && geometry[i] != null) {
+          final StreetsideImage img = new StreetsideImage(imageIds[i], geometry[i], cas[i]);
+          result.add(img);
+        }
+      }
+      if (result.getImages().isEmpty()) {
+        result = null;
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Parses a given {@link JsonObject} as a GeoJSON Feature into a {@link StreetsideSequence}.
+   * @param json the {@link JsonObject} to be parsed
+   * @return a {@link StreetsideSequence} that is parsed from the given {@link JsonObject}. If mandatory information is
+   *         missing from the JSON or it's not meeting the expecting format in another way, <code>null</code> will be
+   *         returned.
+   */
+  public static StreetsideImage decodeBubbleData(final StreetsideImage image) {
+    if (image == null) {
+      return null;
+    }
+    // Declare and instantiate new Streetside object to ensure proper setting of superclass attributes
+    StreetsideImage result = null;
+    if(image.getId() != null ) {
+      result = new StreetsideImage(image.getId(), new LatLon(image.getLa(), image.getLo()), 0.0);
+      result.setAl(image.getAl());
+      result.setRo(image.getRo());
+      result.setPi(image.getPi());
+      result.setHe(image.getHe());
+      result.setBl(image.getBl());
+      result.setMl(image.getMl());
+      result.setNe(image.getNe());
+      result.setPr(image.getPr());
+      result.setNbn(image.getNbn());
+      result.setPbn(image.getPbn());
+      result.setRn(image.getRn());
+      result.setCd(image.getCd());
+    }
+    return result;
+  }
+
+  /**
+   * Parses a given {@link JsonObject} as a GeoJSON Feature into a {@link StreetsideSequence}.
+   * @param json the {@link JsonObject} to be parsed
+   * @return a {@link StreetsideSequence} that is parsed from the given {@link JsonObject}. If mandatory information is
+   *         missing from the JSON or it's not meeting the expecting format in another way, <code>null</code> will be
+   *         returned.
+   */
+  public static StreetsideSequence decodeStreetsideSequence(final JsonObject json) {
+    if (json == null) {
+      return null;
+    }
+    StreetsideSequence result = null;
+
+    if (json.getString("id", null) != null && json.getString("la", null) != null && json.getString("lo", null) != null) {
+        result = new StreetsideSequence(json.getString("id", null), json.getJsonNumber("la").doubleValue(), json.getJsonNumber("lo").doubleValue(), json.getJsonNumber("cd").longValue());
+    }
+
+    return result;
+  }
+
+  /**
+   * Converts a {@link JsonArray} to a java array.
+   * The conversion from {@link JsonValue} to a java type is done by the supplied function.
+   * @param array the array to be converted
+   * @param decodeValueFunction the function used for conversion from {@link JsonValue} to the desired type.
+   * @param clazz the desired type that the elements of the resulting array should have
+   * @return the supplied array converted from {@link JsonArray} to a java array of the supplied type, converted using
+   *         the supplied function. Never <code>null</code>, in case of array==null, an array of length 0 is returned.
+   */
+  @SuppressWarnings("unchecked")
+  private static <T> T[] decodeJsonArray(final JsonArray array, final Function<JsonValue, T> decodeValueFunction, final Class<T> clazz) {
+    final T[] result;
+    if (array == null) {
+      result =  (T[]) Array.newInstance(clazz, 0);
+    } else {
+      result = (T[]) Array.newInstance(clazz, array.size());
+      for (int i = 0; i < result.length; i++) {
+        result[i] = decodeValueFunction.apply(array.get(i));
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Given the JSON object representing the `properties` of a sequence, this method converts you one attribute from the
+   * `coordinateProperties` object to an array of appropriate type.
+   *
+   * For example this is used to convert the `image_keys` JSON array to a String[] array or the `cas` JSON array to a
+   * Double[] array.
+   * @param json the JSON object representing the `properties` of a sequence
+   * @param key the key, which identifies the desired array inside the `coordinateProperties` object to be converted
+   * @param decodeValueFunction a function that converts the {@link JsonValue}s in the JSON array to java objects of the
+   *        desired type
+   * @param clazz the {@link Class} object of the desired type, that the entries of the resulting array should have
+   * @return the resulting array, when converting the desired entry of the `coordinateProperties`.
+   *         Never <code>null</code>. If no `coordinateProperties` are set, or if the desired key is not set or is not
+   *         an array, then an empty array of the desired type is returned.
+   */
+  @SuppressWarnings("unchecked")
+  private static <T> T[] decodeCoordinateProperty(
+    final JsonObject json, final String key, final Function<JsonValue, T> decodeValueFunction, final Class<T> clazz
+  ) {
+    final JsonValue coordinateProperties = json == null ? null : json.get("coordinateProperties");
+    if (coordinateProperties instanceof JsonObject) {
+      JsonValue valueArray = ((JsonObject) coordinateProperties).get(key);
+      if (valueArray instanceof JsonArray) {
+        return decodeJsonArray((JsonArray) valueArray, decodeValueFunction, clazz);
+      }
+    }
+    return (T[]) Array.newInstance(clazz, 0);
+  }
+
+  private static LatLon[] decodeLatLons(final JsonObject json) {
+    final JsonValue coords = json == null ? null : json.get("coordinates");
+    if (coords instanceof JsonArray && "LineString".equals(json.getString("type", null))) {
+      final LatLon[] result = new LatLon[((JsonArray) coords).size()];
+      for (int i = 0; i < ((JsonArray) coords).size(); i++) {
+        final JsonValue coord = ((JsonArray) coords).get(i);
+        if (coord instanceof JsonArray) {
+          result[i] = JsonDecoder.decodeLatLon((JsonArray) coord);
+        }
+      }
+      return result;
+    }
+    return new LatLon[0];
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/package-info.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/package-info.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/src/org/openstreetmap/josm/plugins/streetside/utils/package-info.java	(revision 34317)
@@ -0,0 +1,6 @@
+// License: GPL. For details, see LICENSE file.
+/**
+ * Utility classes for simplifying recurring tasks throughout the project.
+ * These classes are typically not instantiatable and only have static methods.
+ */
+package org.openstreetmap.josm.plugins.streetside.utils;
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/README
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/README	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/README	(revision 34317)
@@ -0,0 +1,9 @@
+
+This directory includes the test resources for the streetside plugin.
+
+
+unit/            test sources (Unit tests, functional tests)
+
+config/          configuration files for running tests
+
+data/            test data
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/requests/changeset.json
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/requests/changeset.json	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/requests/changeset.json	(revision 34317)
@@ -0,0 +1,40 @@
+{
+  "type": "location",
+  "changes": [
+    {
+      "image_key": "wMAqAFr3xE9072G8Al6WLQ",
+      "to": {
+        "geometry": {
+          "coordinates": [13.3323, 50.44612],
+          "type": "Point"
+        },
+        "properties": {"ca": 273.3},
+        "type": "Feature"
+      }
+    },
+    {
+      "image_key": "7erPn382xDMtmfdh0xtvUw",
+      "to": {
+        "geometry": {
+          "coordinates": [13.3328, 50.44619],
+          "type": "Point"
+        },
+        "properties": {},
+        "type": "Feature"
+      }
+    },
+    {
+      "image_key": "31KDbCOzla0fJBtIeoBr1A",
+      "to": {
+        "properties": {"ca": 13.4}
+      }
+    },
+    {
+      "image_key": "invalid image key will be ignored",
+      "to": {
+        "properties": {"ca": 13.4}
+      }
+    }
+  ],
+  "request_comment": "JOSM-created"
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/README.md
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/README.md	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/README.md	(revision 34317)
@@ -0,0 +1,3 @@
+This directory contains example data representative for what the APIv3 typically returns for certain queries.
+
+The examples are taken from https://www.mapillary.com/developer/api-documentation/ .
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/imageDetection.json
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/imageDetection.json	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/imageDetection.json	(revision 34317)
@@ -0,0 +1,45 @@
+{
+  "type": "Feature",
+  "properties": {
+    "area": 0.0015604496002197266,
+    "image_key": "QhRcdlGS_Rn_a1_HTclefg",
+    "key": "gn0llgitnnuqonecevbmf52ino",
+    "package": "trafficsign",
+    "score": 0.710661225175,
+    "shape": {
+      "type": "Polygon",
+      "coordinates": [
+        [
+          [
+            0.330078125,
+            0.466064453125
+          ],
+          [
+            0.3642578125,
+            0.466064453125
+          ],
+          [
+            0.3642578125,
+            0.51171875
+          ],
+          [
+            0.330078125,
+            0.51171875
+          ],
+          [
+            0.330078125,
+            0.466064453125
+          ]
+        ]
+      ]
+    },
+    "value": "regulatory--no-overtaking-by-heavy-goods-vehicles--g1"
+  },
+  "geometry": {
+    "type": "Point",
+    "coordinates": [
+      10.805287,
+      55.321409
+    ]
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/mapObject.json
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/mapObject.json	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/mapObject.json	(revision 34317)
@@ -0,0 +1,21 @@
+{
+  "type": "Feature",
+  "properties": {
+    "accuracy": 1,
+    "altitude": 1.7983143,
+    "first_seen_at": "2016-07-01T12:49:08.553Z",
+    "key": "9f3tl0z2xanom2inyyks65negx",
+    "last_seen_at": "2016-07-01T12:49:08.553Z",
+    "package": "trafficsign",
+    "updated_at": "2017-02-08T15:02:03.778Z",
+    "value": "regulatory--no-entry--g1",
+    "detections": []
+  },
+  "geometry": {
+    "type": "Point",
+    "coordinates": [
+      13.017088890075684,
+      55.60746765136719
+    ]
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/searchImageDetections.json
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/searchImageDetections.json	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/searchImageDetections.json	(revision 34317)
@@ -0,0 +1,95 @@
+{
+  "type": "FeatureCollection",
+  "features": [
+    {
+      "type": "Feature",
+      "properties": {
+        "area": 0.00010585784912109375,
+        "image_key": "33zgql54_tBVvmIij0zrcA",
+        "key": "bzqdn10wz1s1xd3lae3hawgja0",
+        "package": "trafficsign",
+        "score": 0.000001,
+        "shape": {
+          "type": "Polygon",
+          "coordinates": [
+            [
+              [
+                0.42724609375,
+                0.69091796875
+              ],
+              [
+                0.436279296875,
+                0.69091796875
+              ],
+              [
+                0.436279296875,
+                0.70263671875
+              ],
+              [
+                0.42724609375,
+                0.70263671875
+              ],
+              [
+                0.42724609375,
+                0.69091796875
+              ]
+            ]
+          ]
+        },
+        "value": "information--pedestrians-crossing--g1"
+      },
+      "geometry": {
+        "type": "Point",
+        "coordinates": [
+          12.995127,
+          55.550739
+        ]
+      }
+    },
+    {
+      "type": "Feature",
+      "properties": {
+        "area": 0.00010585784912109375,
+        "image_key": "33zgql54_tBVvmIij0zrcA",
+        "key": "uzve1xkyk5qbjwrzaq0do09u1x",
+        "package": "trafficsign",
+        "score": 0.000001,
+        "shape": {
+          "type": "Polygon",
+          "coordinates": [
+            [
+              [
+                0.42724609375,
+                0.69091796875
+              ],
+              [
+                0.436279296875,
+                0.69091796875
+              ],
+              [
+                0.436279296875,
+                0.70263671875
+              ],
+              [
+                0.42724609375,
+                0.70263671875
+              ],
+              [
+                0.42724609375,
+                0.69091796875
+              ]
+            ]
+          ]
+        },
+        "value": "information--pedestrians-crossing--g1"
+      },
+      "geometry": {
+        "type": "Point",
+        "coordinates": [
+          12.995127,
+          55.550739
+        ]
+      }
+    }
+  ]
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/searchImages.json
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/searchImages.json	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/searchImages.json	(revision 34317)
@@ -0,0 +1,43 @@
+{
+  "type": "FeatureCollection",
+  "features": [
+    {
+      "type": "Feature",
+      "properties": {
+        "ca": 232.73019999999997,
+        "camera_make": "Apple",
+        "captured_at": "2017-04-10T05:51:30.334Z",
+        "key": "_yA5uXuSNugmsK5VucU6Bg",
+        "pano": false,
+        "user_key": "UtczWn8y3afb0GQVW-AiOQ",
+        "username": "xtyou"
+      },
+      "geometry": {
+        "type": "Point",
+        "coordinates": [
+          2.215628000000038,
+          48.90262200000001
+        ]
+      }
+    },
+    {
+      "type": "Feature",
+      "properties": {
+        "ca": 237.21129999999994,
+        "camera_make": "Apple",
+        "captured_at": "2017-04-10T05:51:26.853Z",
+        "key": "nmF-Wq4EvVTgAUmBicSCCg",
+        "pano": false,
+        "user_key": "UtczWn8y3afb0GQVW-AiOQ",
+        "username": "xtyou"
+      },
+      "geometry": {
+        "type": "Point",
+        "coordinates": [
+          2.2156680000000506,
+          48.90267399999999
+        ]
+      }
+    }
+  ]
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/searchMapObjects.json
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/searchMapObjects.json	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/searchMapObjects.json	(revision 34317)
@@ -0,0 +1,31 @@
+{
+  "type": "FeatureCollection",
+  "features": [
+    {
+      "type": "Feature",
+      "properties": {
+        "accuracy": 1,
+        "altitude": 3.688496,
+        "first_seen_at": "2016-10-16T09:42:56.060Z",
+        "key": "qpku21qv8rjn7fll1v671732th",
+        "last_seen_at": "2016-10-16T09:42:56.060Z",
+        "package": "trafficsign",
+        "updated_at": "2016-11-29T12:21:22.275Z",
+        "value": "regulatory--no-parking--g1",
+        "detections": [
+          {
+            "detection_key": "cpatpdftmogffmhihau9792tua",
+            "image_key": "bsw3H-ajJD42zZSg2P64hA"
+          }
+        ]
+      },
+      "geometry": {
+        "type": "Point",
+        "coordinates": [
+          13.005650520324707,
+          55.608367919921875
+        ]
+      }
+    }
+  ]
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/searchSequences.json
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/searchSequences.json	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/searchSequences.json	(revision 34317)
@@ -0,0 +1,51 @@
+{
+  "type": "FeatureCollection",
+  "features": [
+    {
+      "type": "Feature",
+      "properties": {
+        "camera_make": "Apple",
+        "captured_at": "2016-03-14T13:44:53.860Z",
+        "created_at": "2016-03-17T10:47:53.106Z",
+        "coordinateProperties": {
+          "cas": [
+            323.0319999999999,
+            320.8918,
+            333.62239999999997,
+            329.94820000000004
+          ],
+          "image_keys": [
+            "LwrHXqFRN_pszCopTKHF_Q",
+            "Aufjv2hdCKwg9LySWWVSwg",
+            "QEVZ1tp-PmrwtqhSwdW9fQ",
+            "G_SIwxNcioYeutZuA8Rurw"
+          ]
+        },
+        "key": "LMlIPUNhaj24h_q9v4ArNw",
+        "pano": false,
+        "user_key": "AGfe-07BEJX0-kxpu9J3rA"
+      },
+      "geometry": {
+        "type": "LineString",
+        "coordinates": [
+          [
+            16.432958,
+            7.246497
+          ],
+          [
+            16.432955,
+            7.246567
+          ],
+          [
+            16.432971,
+            7.248372
+          ],
+          [
+            16.432976,
+            7.249027
+          ]
+        ]
+      }
+    }
+  ]
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/sequence.json
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/sequence.json	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/sequence.json	(revision 34317)
@@ -0,0 +1,34 @@
+{
+  "type": "Feature",
+  "properties": {
+    "camera_make": "Apple",
+    "captured_at": "2016-03-14T13:44:37.206Z",
+    "created_at": "2016-03-15T08:48:40.592Z",
+    "coordinateProperties": {
+      "cas": [
+        96.71454,
+        96.47705000000002
+      ],
+      "image_keys": [
+        "76P0YUrlDD_lF6J7Od3yoA",
+        "Ap_8E0BwoAqqewhJaEbFyQ"
+      ]
+    },
+    "key": "cHBf9e8n0pG8O0ZVQHGFBQ",
+    "pano": false,
+    "user_key": "AGfe-07BEJX0-kxpu9J3rA"
+  },
+  "geometry": {
+    "type": "LineString",
+    "coordinates": [
+      [
+        16.43279,
+        7.246085
+      ],
+      [
+        16.432799,
+        7.246082
+      ]
+    ]
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/userProfile.json
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/userProfile.json	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/userProfile.json	(revision 34317)
@@ -0,0 +1,7 @@
+{
+  "about": "Mapillary and Mapping!",
+  "avatar": "https://d4vkkeqw582u.cloudfront.net/3f9f044b34b498ddfb9afbb6/profile.png",
+  "created_at": "2013-09-18T16:52:28.042Z",
+  "key": "2BJl04nvnfW1y2GNaj7x5w",
+  "username": "gyllen"
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/userProfile2.json
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/userProfile2.json	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/api/v3/responses/userProfile2.json	(revision 34317)
@@ -0,0 +1,7 @@
+{
+  "about": "Having a non-image avatar",
+  "avatar": "https://example.org",
+  "created_at": "2016-01-31T01:47:28.000+0500",
+  "key": "abcdefg1",
+  "username": "mapillary_userÄ2!"
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/exifTestImages/dateTimeOnly.metadata.txt
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/exifTestImages/dateTimeOnly.metadata.txt	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/exifTestImages/dateTimeOnly.metadata.txt	(revision 34317)
@@ -0,0 +1,1 @@
+add Exif.Photo.DateTimeOriginal 2015:12:24 01:02:03
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/exifTestImages/generateExifTaggedImages.sh
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/exifTestImages/generateExifTaggedImages.sh	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/exifTestImages/generateExifTaggedImages.sh	(revision 34317)
@@ -0,0 +1,10 @@
+#!/bin/bash
+rm latLonOnly.jpg
+rm dateTimeOnly.jpg
+rm gpsDirectionOnly.jpg
+cp -T untagged.jpg latLonOnly.jpg
+cp -T untagged.jpg dateTimeOnly.jpg
+cp -T untagged.jpg gpsDirectionOnly.jpg
+exiv2 -m latLonOnly.metadata.txt latLonOnly.jpg
+exiv2 -m dateTimeOnly.metadata.txt dateTimeOnly.jpg
+exiv2 -m gpsDirectionOnly.metadata.txt gpsDirectionOnly.jpg
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/exifTestImages/gpsDirectionOnly.metadata.txt
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/exifTestImages/gpsDirectionOnly.metadata.txt	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/exifTestImages/gpsDirectionOnly.metadata.txt	(revision 34317)
@@ -0,0 +1,1 @@
+add Exif.GPSInfo.GPSImgDirection 4273/100
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/exifTestImages/latLonOnly.metadata.txt
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/exifTestImages/latLonOnly.metadata.txt	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/exifTestImages/latLonOnly.metadata.txt	(revision 34317)
@@ -0,0 +1,4 @@
+add Exif.GPSInfo.GPSLatitude 55/1 36/1 19/1
+add Exif.GPSInfo.GPSLatitudeRef N
+add Exif.GPSInfo.GPSLongitude 13/1 0/1 1/2
+add Exif.GPSInfo.GPSLongitudeRef E
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/data/preferences/preferences.xml
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/data/preferences/preferences.xml	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/data/preferences/preferences.xml	(revision 34317)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<preferences xmlns="http://josm.openstreetmap.de/preferences-1.0">
+  <tag key='expert' value='true'/>
+  <tag key='language' value='en'/>
+</preferences>
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImageTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImageTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideAbstractImageTest.java	(revision 34317)
@@ -0,0 +1,79 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.TimeZone;
+
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil.StreetsideTestRules;
+import org.openstreetmap.josm.spi.preferences.Config;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+public class StreetsideAbstractImageTest {
+
+  @Rule
+  public JOSMTestRules rules = new StreetsideTestRules().platform();
+
+  /**
+   * Test method for {@link org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage#getDate()}.
+   */
+  @Ignore
+  @Test
+  public void testGetDate() {
+    TimeZone.setDefault(TimeZone.getTimeZone("GMT+0745"));
+
+    StreetsideAbstractImage mai = new StreetsideImportedImage(CubemapUtils.IMPORTED_ID, new LatLon(0, 0), 0, null);
+    //mai.setCapturedAt(1044087606000l); // in timezone GMT+0745 this is Saturday, February 1, 2003 16:05:06
+    mai.setHe(1525381954996l); // in timezone PST this is Thu May 03 2018 14:12:34 GMT-0700 (PDT)
+
+
+    testGetDate("05/03/2018", mai, false, false, false);
+    testGetDate("05/03/2018", mai, false, false, true);
+    testGetDate("05/03/2018 - 2:12:34 PM (GMT-07:00)", mai, false, true, false);
+    testGetDate("05/03/2018 - 2:12:34 (GMT-07:00)", mai, false, true, true);
+    testGetDate("2018-05-03", mai, true, false, false);
+    testGetDate("2018-05-03", mai, true, false, true);
+    testGetDate("2018-05-03 - 2:12:34 PM (GMT-07:00)", mai, true, true, false);
+    testGetDate("2018-05-03 - 2:12:34 (GMT-07:00)", mai, true, true, true);
+
+    TimeZone.setDefault(TimeZone.getTimeZone("GMT+0300"));
+    //mai.setCapturedAt(1440671802000l); // in Timezone GMT-0123 this is Thursday, August 27, 2015 09:13:42 AM
+    mai.setHe(1440671802000l); // in Timezone GMT-0123 this is Thursday, August 27, 2015 09:13:42 AM
+
+    // TODO: fix testGetDate @rrh
+    testGetDate("03/05/2018 - 04:57:34 (GMT+07:45)", mai, false, true, true);
+  }
+
+  private static void testGetDate(String expected, StreetsideAbstractImage img,
+      boolean isoDates, boolean displayHour, boolean format24) {
+    Config.getPref().putBoolean("iso.dates", isoDates);
+    Config.getPref().putBoolean("streetside.display-hour", displayHour);
+    Config.getPref().putBoolean("streetside.format-24", format24);
+    assertEquals(expected, img.getDate());
+  }
+
+  @Test
+  public void testIsModified() {
+    StreetsideImage img = new StreetsideImage("key___________________", new LatLon(0, 0), 0);
+    assertFalse(img.isModified());
+    img.turn(1e-4);
+    img.stopMoving();
+    assertTrue(img.isModified());
+    img.turn(-1e-4);
+    img.stopMoving();
+    assertFalse(img.isModified());
+    img.move(1e-4, 1e-4);
+    img.stopMoving();
+    assertTrue(img.isModified());
+    img.move(-1e-4, -1e-4);
+    img.stopMoving();
+    assertFalse(img.isModified());
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideDataTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideDataTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideDataTest.java	(revision 34317)
@@ -0,0 +1,158 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil.StreetsideTestRules;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+/**
+ * Tests for {@link StreetsideData} class.
+ *
+ * @author nokutu
+ * @see StreetsideData
+ */
+public class StreetsideDataTest {
+
+  @Rule
+  public JOSMTestRules rules = new StreetsideTestRules().platform();
+
+  private StreetsideData data;
+  private StreetsideImage img1;
+  private StreetsideImage img2;
+  private StreetsideImage img3;
+  private StreetsideImage img4;
+
+  /**
+   * Creates a sample {@link StreetsideData} objects, 4 {@link StreetsideImage}
+   * objects and a {@link StreetsideSequence} object.
+   */
+  @Before
+  public void setUp() {
+    img1 = new StreetsideImage("key1__________________", new LatLon(0.1, 0.1), 90);
+    img2 = new StreetsideImage("key2__________________", new LatLon(0.2, 0.2), 90);
+    img3 = new StreetsideImage("key3__________________", new LatLon(0.3, 0.3), 90);
+    img4 = new StreetsideImage("key4__________________", new LatLon(0.4, 0.4), 90);
+    final StreetsideSequence seq = new StreetsideSequence();
+
+    seq.add(Arrays.asList(img1, img2, img3, img4));
+
+    data = new StreetsideData();
+    data.addAll(new ConcurrentSkipListSet<>(seq.getImages()));
+  }
+
+  /**
+   * Tests the addition of new images. If a second image with the same key as
+   * another one in the database, the one that is being added should be ignored.
+   */
+  @Test
+  public void addTest() {
+    data = new StreetsideData();
+    assertEquals(0, data.getImages().size());
+    data.add(img1);
+    assertEquals(1, data.getImages().size());
+    data.add(img1);
+    assertEquals(1, data.getImages().size());
+    data.addAll(new ConcurrentSkipListSet<>(Arrays.asList(img2, img3)));
+    assertEquals(3, data.getImages().size());
+    data.addAll(new ConcurrentSkipListSet<>(Arrays.asList(img3, img4)));
+    assertEquals(4, data.getImages().size());
+  }
+
+  /**
+   * Test that the size is properly calculated.
+   */
+  @Test
+  public void sizeTest() {
+    assertEquals(4, data.getImages().size());
+    data.add(new StreetsideImage("key5__________________", new LatLon(0.1, 0.1), 90));
+    assertEquals(5, data.getImages().size());
+  }
+
+  /**
+   * Test the {@link StreetsideData#setHighlightedImage(StreetsideAbstractImage)}
+   * and {@link StreetsideData#getHighlightedImage()} methods.
+   */
+  @Test
+  public void highlighTest() {
+    data.setHighlightedImage(img1);
+    assertEquals(img1, data.getHighlightedImage());
+
+    data.setHighlightedImage(null);
+    assertEquals(null, data.getHighlightedImage());
+  }
+
+  /**
+   * Tests the selection of images.
+   */
+  @Ignore
+  @Test
+  public void selectTest() {
+    data.setSelectedImage(img1);
+    assertEquals(img1, data.getSelectedImage());
+
+    data.setSelectedImage(img4);
+    assertEquals(img4, data.getSelectedImage());
+
+    data.setSelectedImage(null);
+    assertEquals(null, data.getSelectedImage());
+  }
+
+  /**
+   * Tests the {@link StreetsideData#selectNext()} and
+   * {@link StreetsideData#selectPrevious()} methods.
+   */
+  @Ignore
+  @Test
+  public void nextAndPreviousTest() {
+    data.setSelectedImage(img1);
+
+    data.selectNext();
+    assertEquals(img2, data.getSelectedImage());
+    data.selectNext();
+    assertEquals(img3, data.getSelectedImage());
+    data.selectPrevious();
+    assertEquals(img2, data.getSelectedImage());
+
+    data.setSelectedImage(null);
+  }
+
+  @Ignore
+  @Test(expected=IllegalStateException.class)
+  public void nextOfNullImgTest() {
+    data.setSelectedImage(null);
+    data.selectNext();
+  }
+
+  @Ignore
+  @Test(expected=IllegalStateException.class)
+  public void previousOfNullImgTest() {
+    data.setSelectedImage(null);
+    data.selectPrevious();
+  }
+
+  /**
+   * Test the multiselection of images. When a new image is selected, the
+   * multiselected List should reset.
+   */
+  @Ignore
+  @Test
+  public void multiSelectTest() {
+    assertEquals(0, data.getMultiSelectedImages().size());
+    data.setSelectedImage(img1);
+    assertEquals(1, data.getMultiSelectedImages().size());
+    data.addMultiSelectedImage(img2);
+    assertEquals(2, data.getMultiSelectedImages().size());
+    data.setSelectedImage(img1);
+    assertEquals(1, data.getMultiSelectedImages().size());
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideLayerTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideLayerTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideLayerTest.java	(revision 34317)
@@ -0,0 +1,88 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.imagery.ImageryInfo;
+import org.openstreetmap.josm.gui.layer.ImageryLayer;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil.StreetsideTestRules;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+public class StreetsideLayerTest {
+
+  @Rule
+  public JOSMTestRules rules = new StreetsideTestRules().main().preferences().projection();
+
+  private static Layer getDummyLayer() {
+    return ImageryLayer.create(new ImageryInfo("dummy", "https://example.org"));
+  }
+
+  @Ignore
+  @Test
+  public void testGetIcon() {
+    assertNotNull(StreetsideLayer.getInstance().getIcon());
+  }
+
+  @Ignore
+  @Test
+  public void testIsMergable() {
+    assertFalse(StreetsideLayer.getInstance().isMergable(getDummyLayer()));
+  }
+
+  @Ignore
+  @Test(expected = UnsupportedOperationException.class)
+  public void testMergeFrom() {
+    StreetsideLayer.getInstance().mergeFrom(getDummyLayer());
+  }
+
+  @Ignore
+  @Test
+  public void testSetVisible() {
+    StreetsideLayer.getInstance().getData().add(new StreetsideImportedImage(CubemapUtils.IMPORTED_ID, new LatLon(0.0, 0.0), 0.0, new File("")));
+    StreetsideLayer.getInstance().getData().add(new StreetsideImportedImage(CubemapUtils.IMPORTED_ID, new LatLon(0.0, 0.0), 0.0, new File("")));
+    StreetsideImportedImage invisibleImage = new StreetsideImportedImage(CubemapUtils.IMPORTED_ID, new LatLon(0.0, 0.0), 0.0, new File(""));
+    invisibleImage.setVisible(false);
+    StreetsideLayer.getInstance().getData().add(invisibleImage);
+
+    StreetsideLayer.getInstance().setVisible(false);
+    for (StreetsideAbstractImage img : StreetsideLayer.getInstance().getData().getImages()) {
+      assertEquals(false, img.isVisible());
+    }
+
+
+    StreetsideLayer.getInstance().setVisible(true);
+    for (StreetsideAbstractImage img : StreetsideLayer.getInstance().getData().getImages()) {
+      assertEquals(true, img.isVisible());
+    }
+  }
+
+  @Ignore
+  @Test
+  public void testGetInfoComponent() {
+    Object comp = StreetsideLayer.getInstance().getInfoComponent();
+    assertTrue(comp instanceof String);
+    assertTrue(((String) comp).length() >= 9);
+  }
+
+  @Ignore
+  @Test
+  public void testClearInstance() {
+    StreetsideLayer.getInstance();
+    assertTrue(StreetsideLayer.hasInstance());
+    JOSMTestRules.cleanLayerEnvironment();
+    assertFalse(StreetsideLayer.hasInstance());
+    StreetsideLayer.getInstance();
+    assertTrue(StreetsideLayer.hasInstance());
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideSequenceTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideSequenceTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/StreetsideSequenceTest.java	(revision 34317)
@@ -0,0 +1,77 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+
+/**
+ * Tests for the {@link StreetsideSequence} class.
+ *
+ * @author nokutu
+ * @see StreetsideSequence
+ */
+public class StreetsideSequenceTest {
+
+  private final StreetsideImage img1 = new StreetsideImage("key1", new LatLon(0.1, 0.1), 90);
+  private final StreetsideImage img2 = new StreetsideImage("key2", new LatLon(0.2, 0.2), 90);
+  private final StreetsideImage img3 = new StreetsideImage("key3", new LatLon(0.3, 0.3), 90);
+  private final StreetsideImage img4 = new StreetsideImage("key4", new LatLon(0.4, 0.4), 90);
+  private final StreetsideImage imgWithoutSeq = new StreetsideImage("key5", new LatLon(0.5, 0.5), 90);
+  private final StreetsideSequence seq = new StreetsideSequence();
+
+  /**
+   * Creates 4 {@link StreetsideImage} objects and puts them in a
+   * {@link StreetsideSequence} object.
+   */
+  @Before
+  public void setUp() {
+    seq.add(Arrays.asList(img1, img2, img3, img4));
+  }
+
+  /**
+   * Tests the {@link StreetsideSequence#next(StreetsideAbstractImage)} and
+   * {@link StreetsideSequence#previous(StreetsideAbstractImage)}.
+   */
+  @Test
+  public void nextAndPreviousTest() {
+    assertEquals(img2, img1.next());
+    assertEquals(img1, img2.previous());
+    assertEquals(img3, img2.next());
+    assertEquals(img2, img3.previous());
+    assertEquals(img4, img3.next());
+    assertEquals(img3, img4.previous());
+
+
+    assertNull(img4.next());
+    assertNull(img1.previous());
+
+    assertNull(imgWithoutSeq.next());
+    assertNull(imgWithoutSeq.previous());
+
+    // Test IllegalArgumentException when asking for the next image of an image
+    // that is not in the sequence.
+    try {
+      seq.next(imgWithoutSeq);
+      fail();
+    } catch (IllegalArgumentException e) {
+      assertTrue(true);
+    }
+    // Test IllegalArgumentException when asking for the previous image of an
+    // image that is not in the sequence.
+    try {
+      seq.previous(imgWithoutSeq);
+      fail();
+    } catch (IllegalArgumentException e) {
+      assertTrue(true);
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cache/CachesTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cache/CachesTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cache/CachesTest.java	(revision 34317)
@@ -0,0 +1,14 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.cache;
+
+import org.junit.Test;
+
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil;
+
+public class CachesTest {
+
+  @Test
+  public void testUtilityClass() {
+    TestUtil.testUtilityClass(Caches.class);
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cache/StreetsideCacheTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cache/StreetsideCacheTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/cache/StreetsideCacheTest.java	(revision 34317)
@@ -0,0 +1,37 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.cache;
+//License: GPL. For details, see LICENSE file.
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.openstreetmap.josm.plugins.streetside.cache.StreetsideCache.Type;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil.StreetsideTestRules;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+public class StreetsideCacheTest {
+
+  @Rule
+  public JOSMTestRules rules = new StreetsideTestRules().preferences();
+
+  @Test
+  public void test() {
+    StreetsideCache cache = new StreetsideCache("00000", Type.FULL_IMAGE);
+    assertNotNull(cache.getUrl());
+    assertNotNull(cache.getCacheKey());
+
+    assertFalse(cache.isObjectLoadable());
+
+    cache = new StreetsideCache("00000", Type.THUMBNAIL);
+    assertNotNull(cache.getCacheKey());
+    assertNotNull(cache.getUrl());
+
+    cache = new StreetsideCache(null, null);
+    assertNull(cache.getCacheKey());
+    assertNull(cache.getUrl());
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/ImageDisplayTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/ImageDisplayTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/ImageDisplayTest.java	(revision 34317)
@@ -0,0 +1,92 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui;
+
+import static org.junit.Assert.assertEquals;
+
+import java.awt.GraphicsEnvironment;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseWheelEvent;
+import java.awt.image.BufferedImage;
+
+import javax.swing.JFrame;
+
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil.StreetsideTestRules;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+/**
+ * Tests {@link StreetsideImageDisplay}
+ */
+public class ImageDisplayTest {
+
+  @Rule
+  public JOSMTestRules rules = new StreetsideTestRules().preferences();
+
+  private static final BufferedImage DUMMY_IMAGE = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
+
+  @Ignore
+  @Test
+  public void testImagePersistence() {
+    StreetsideImageDisplay display = new StreetsideImageDisplay();
+    display.setImage(DUMMY_IMAGE, null);
+    assertEquals(DUMMY_IMAGE, display.getImage());
+  }
+
+  /**
+   * This test does not check if the scroll events result in the correct changes in the {@link StreetsideImageDisplay},
+   * it only checks if the tested method runs through.
+   */
+  @Ignore
+  @Test
+  public void testMouseWheelMoved() {
+    if (GraphicsEnvironment.isHeadless()) {
+      return;
+    }
+    StreetsideImageDisplay display = new StreetsideImageDisplay();
+    final MouseWheelEvent dummyScroll = new MouseWheelEvent(display, 42, System.currentTimeMillis(), 0, 0, 0, 0, false, MouseWheelEvent.WHEEL_UNIT_SCROLL, 1, 3);
+    display.getMouseWheelListeners()[0].mouseWheelMoved(dummyScroll);
+
+    display.setImage(DUMMY_IMAGE, null);
+
+    display.getMouseWheelListeners()[0].mouseWheelMoved(dummyScroll);
+
+    // This is necessary to make the size of the component > 0. If you know a more elegant solution, feel free to change it.
+    JFrame frame = new JFrame();
+    frame.setSize(42, 42);
+    frame.getContentPane().add(display);
+    frame.pack();
+
+    display.getMouseWheelListeners()[0].mouseWheelMoved(dummyScroll);
+  }
+
+  /**
+   * This test does not check if the scroll events result in the correct changes in the {@link StreetsideImageDisplay},
+   * it only checks if the tested method runs through.
+   */
+  @Ignore
+  @Test
+  public void testMouseClicked() {
+    if (GraphicsEnvironment.isHeadless()) {
+      return;
+    }
+    for (int button = 1; button <= 3; button++) {
+      StreetsideImageDisplay display = new StreetsideImageDisplay();
+      final MouseEvent dummyClick = new MouseEvent(display, 42, System.currentTimeMillis(), 0, 0, 0, 1, false, button);
+      display.getMouseListeners()[0].mouseClicked(dummyClick);
+
+      display.setImage(DUMMY_IMAGE, null);
+
+      display.getMouseListeners()[0].mouseClicked(dummyClick);
+
+      // This is necessary to make the size of the component > 0. If you know a more elegant solution, feel free to change it.
+      JFrame frame = new JFrame();
+      frame.setSize(42, 42);
+      frame.getContentPane().add(display);
+      frame.pack();
+
+      display.getMouseListeners()[0].mouseClicked(dummyClick);
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/StreetsidePreferenceSettingTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/StreetsidePreferenceSettingTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/StreetsidePreferenceSettingTest.java	(revision 34317)
@@ -0,0 +1,144 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.openstreetmap.josm.plugins.streetside.utils.TestUtil.getPrivateFieldValue;
+
+import java.awt.GraphicsEnvironment;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SpinnerNumberModel;
+
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.openstreetmap.josm.data.preferences.BooleanProperty;
+import org.openstreetmap.josm.data.preferences.StringProperty;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane;
+import org.openstreetmap.josm.plugins.streetside.io.download.StreetsideDownloader.DOWNLOAD_MODE;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil.StreetsideTestRules;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.tools.I18n;
+
+public class StreetsidePreferenceSettingTest {
+
+  @Rule
+  public JOSMTestRules rules = new StreetsideTestRules().main();
+
+  @Ignore
+  @Test
+  public void testAddGui() {
+    if (GraphicsEnvironment.isHeadless()) {
+      return;
+    }
+    PreferenceTabbedPane tabs = new PreferenceTabbedPane();
+    tabs.buildGui();
+    int displayTabs = tabs.getDisplayPreference().getTabPane().getTabCount();
+    StreetsidePreferenceSetting setting = new StreetsidePreferenceSetting();
+    setting.addGui(tabs);
+    assertEquals(displayTabs + 1, tabs.getDisplayPreference().getTabPane().getTabCount());
+    assertEquals(tabs.getDisplayPreference(), setting.getTabPreferenceSetting(tabs));
+  }
+
+  @Ignore
+  @Test
+  public void testIsExpert() {
+    assertFalse(new StreetsidePreferenceSetting().isExpert());
+  }
+
+  @Ignore
+  @Test
+  public void testLoginLogout() {
+    if (GraphicsEnvironment.isHeadless()) {
+      return;
+    }
+    PreferenceTabbedPane tabs = new PreferenceTabbedPane();
+    tabs.buildGui();
+    StreetsidePreferenceSetting setting = new StreetsidePreferenceSetting();
+    setting.addGui(tabs);
+    setting.onLogout();
+
+    assertEquals(I18n.tr("Login"), ((JButton) getPrivateFieldValue(setting, "loginButton")).getText());
+    assertEquals(I18n.tr("You are currently not logged in."), ((JLabel) getPrivateFieldValue(setting, "loginLabel")).getText());
+    assertFalse(((JPanel) getPrivateFieldValue(setting, "loginPanel")).isAncestorOf(((JButton) getPrivateFieldValue(setting, "logoutButton"))));
+    assertTrue(((JPanel) getPrivateFieldValue(setting, "loginPanel")).isAncestorOf(((JButton) getPrivateFieldValue(setting, "loginButton"))));
+
+    String username = "TheStreetsideUsername";
+    setting.onLogin(username);
+
+    assertEquals(I18n.tr("Login"), ((JButton) getPrivateFieldValue(setting, "loginButton")).getText());
+    assertEquals(I18n.tr("You are logged in as ''{0}''.", username), ((JLabel) getPrivateFieldValue(setting, "loginLabel")).getText());
+    assertTrue(((JPanel) getPrivateFieldValue(setting, "loginPanel")).isAncestorOf(((JButton) getPrivateFieldValue(setting, "logoutButton"))));
+    assertFalse(((JPanel) getPrivateFieldValue(setting, "loginPanel")).isAncestorOf(((JButton) getPrivateFieldValue(setting, "loginButton"))));
+  }
+
+  @SuppressWarnings("unchecked")
+  @Ignore
+  @Test
+  public void testOk() {
+    StreetsidePreferenceSetting settings = new StreetsidePreferenceSetting();
+
+    // Initialize the properties with some arbitrary value to make sure they are not unset
+    new StringProperty("streetside.display-hour", "default").put("arbitrary");
+    new StringProperty("streetside.format-24", "default").put("arbitrary");
+    new StringProperty("streetside.move-to-picture", "default").put("arbitrary");
+    new StringProperty("streetside.hover-enabled", "default").put("arbitrary");
+    new StringProperty("streetside.download-mode", "default").put("arbitrary");
+    new StringProperty("streetside.prefetch-image-count", "default").put("arbitrary");
+
+    // Test checkboxes
+    settings.ok();
+    assertPropertyMatchesCheckboxSelection((JCheckBox) getPrivateFieldValue(settings, "displayHour"), "streetside.display-hour");
+    assertPropertyMatchesCheckboxSelection((JCheckBox) getPrivateFieldValue(settings, "format24"), "streetside.format-24");
+    assertPropertyMatchesCheckboxSelection((JCheckBox) getPrivateFieldValue(settings, "moveTo"), "streetside.move-to-picture");
+    assertPropertyMatchesCheckboxSelection((JCheckBox) getPrivateFieldValue(settings, "hoverEnabled"), "streetside.hover-enabled");
+    assertEquals(String.valueOf(((SpinnerNumberModel) getPrivateFieldValue(settings, "preFetchSize")).getNumber().intValue()), new StringProperty("streetside.prefetch-image-count", "default").get());
+
+    // Toggle state of the checkboxes
+    toggleCheckbox((JCheckBox) getPrivateFieldValue(settings, "displayHour"));
+    toggleCheckbox((JCheckBox) getPrivateFieldValue(settings, "format24"));
+    toggleCheckbox((JCheckBox) getPrivateFieldValue(settings, "moveTo"));
+    toggleCheckbox((JCheckBox) getPrivateFieldValue(settings, "hoverEnabled"));
+    ((SpinnerNumberModel) getPrivateFieldValue(settings, "preFetchSize")).setValue(73);
+
+    // Test the second state of the checkboxes
+    settings.ok();
+    assertPropertyMatchesCheckboxSelection((JCheckBox) getPrivateFieldValue(settings, "displayHour"), "streetside.display-hour");
+    assertPropertyMatchesCheckboxSelection((JCheckBox) getPrivateFieldValue(settings, "format24"), "streetside.format-24");
+    assertPropertyMatchesCheckboxSelection((JCheckBox) getPrivateFieldValue(settings, "moveTo"), "streetside.move-to-picture");
+    assertPropertyMatchesCheckboxSelection((JCheckBox) getPrivateFieldValue(settings, "hoverEnabled"), "streetside.hover-enabled");
+    assertEquals(String.valueOf(((SpinnerNumberModel) getPrivateFieldValue(settings, "preFetchSize")).getNumber().intValue()), new StringProperty("streetside.prefetch-image-count", "default").get());
+
+    // Test combobox
+    for (int i = 0; i < ((JComboBox<String>) getPrivateFieldValue(settings, "downloadModeComboBox")).getItemCount(); i++) {
+      ((JComboBox<String>) getPrivateFieldValue(settings, "downloadModeComboBox")).setSelectedIndex(i);
+      settings.ok();
+      assertEquals(
+        new StringProperty("streetside.download-mode", "default").get(),
+        DOWNLOAD_MODE.fromLabel(
+          ((JComboBox<String>) getPrivateFieldValue(settings, "downloadModeComboBox")).getSelectedItem().toString()
+        ).getPrefId()
+      );
+    }
+  }
+
+  /**
+   * Checks, if a certain {@link BooleanProperty} (identified by the {@code propName} attribute) matches the selected-state of the given {@link JCheckBox}
+   * @param cb the {@link JCheckBox}, which should be checked against the {@link BooleanProperty}
+   * @param propName the name of the property against which the selected-state of the given {@link JCheckBox} should be checked
+   */
+  private static void assertPropertyMatchesCheckboxSelection(JCheckBox cb, String propName) {
+    assertEquals(cb.isSelected(), new BooleanProperty(propName, !cb.isSelected()).get());
+  }
+
+  private static void toggleCheckbox(JCheckBox jcb) {
+    jcb.setSelected(!jcb.isSelected());
+  }
+
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/boilerplate/SelectableLabelTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/boilerplate/SelectableLabelTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/gui/boilerplate/SelectableLabelTest.java	(revision 34317)
@@ -0,0 +1,19 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.gui.boilerplate;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class SelectableLabelTest {
+  @Test
+  public void test() {
+    SelectableLabel l1 = new SelectableLabel();
+    assertFalse(l1.isEditable());
+    SelectableLabel l2 = new SelectableLabel("some text");
+    assertTrue(l2.getText().contains("some text"));
+    assertFalse(l2.isEditable());
+
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/history/StreetsideRecordTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/history/StreetsideRecordTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/history/StreetsideRecordTest.java	(revision 34317)
@@ -0,0 +1,238 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.history;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.history.commands.CommandJoin;
+import org.openstreetmap.josm.plugins.streetside.history.commands.CommandMove;
+import org.openstreetmap.josm.plugins.streetside.history.commands.CommandTurn;
+import org.openstreetmap.josm.plugins.streetside.history.commands.CommandUnjoin;
+import org.openstreetmap.josm.plugins.streetside.history.commands.StreetsideCommand;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil.StreetsideTestRules;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+/**
+ * Tests the command record system.
+ *
+ * @author nokutu
+ */
+public class StreetsideRecordTest {
+
+  @Rule
+  public JOSMTestRules rules = new StreetsideTestRules().main().projection();
+
+  private StreetsideRecord record;
+  private StreetsideImage img1;
+  private StreetsideImage img2;
+  private StreetsideImage img3;
+
+  /**
+   * Creates a new {@link StreetsideRecord} object and 3 {@link StreetsideImage}
+   * objects.
+   */
+  @Before
+  public void setUp() {
+    record = new StreetsideRecord();
+    img1 = new StreetsideImage("key1__________________", new LatLon(0.1, 0.1), 0.1);
+    img2 = new StreetsideImage("key2__________________", new LatLon(0.2, 0.2), 0.2);
+    img3 = new StreetsideImage("key3__________________", new LatLon(0.3, 0.3), 0.3);
+    if (StreetsideLayer.hasInstance() && StreetsideLayer.getInstance().getData().getImages().size() >= 1) {
+      StreetsideLayer.getInstance().getData().getImages().clear();
+    }
+  }
+
+  /**
+   * Test commands in general.
+   */
+  @Test
+  public void commandTest() {
+    StreetsideCommand cmd12 = new CommandMove(
+            new ConcurrentSkipListSet<>(Arrays.asList(img1, img2)),
+            0.1, 0.1);
+    StreetsideCommand cmd23 = new CommandMove(
+            new ConcurrentSkipListSet<>(Arrays.asList(img2, img3)),
+            0.1, 0.1);
+    StreetsideCommand cmd13 = new CommandMove(
+            new ConcurrentSkipListSet<>(Arrays.asList(img1, img3)),
+            0.1, 0.1);
+    StreetsideCommand cmd1 = new CommandMove(
+            new ConcurrentSkipListSet<>(Collections.singletonList(img1)), 0.1, 0.1);
+    StreetsideCommand cmd31 = new CommandMove(
+            new ConcurrentSkipListSet<>(Arrays.asList(img3, img1)),
+            0.2, 0.2);
+    record.addCommand(cmd12);
+    record.addCommand(cmd23);
+
+    assertEquals(1, record.position);
+    assertEquals(2, record.commandList.size());
+
+    record.undo();
+
+    assertEquals(0, record.position);
+    assertEquals(2, record.commandList.size());
+
+    record.addCommand(cmd1);
+
+    assertEquals(1, record.position);
+
+    record.addCommand(cmd13);
+
+    assertEquals(2, record.position);
+    assertEquals(3, record.commandList.size());
+
+    record.undo();
+    record.redo();
+
+    assertEquals(2, record.position);
+    assertEquals(3, record.commandList.size());
+
+    record.addCommand(cmd31);
+
+    assertEquals(2, record.position);
+    assertEquals(3, record.commandList.size());
+
+    record.addCommand(cmd1);
+
+    assertEquals(3, record.position);
+    assertEquals(4, record.commandList.size());
+  }
+
+  /**
+   * Tests {@link CommandMove} class.
+   */
+  @Test
+  public void commandMoveTest() {
+    CommandMove cmd1 = new CommandMove(
+            new ConcurrentSkipListSet<>(Arrays.asList(img1, img2)),
+            0.1, 0.1);
+    CommandMove cmd2 = new CommandMove(
+            new ConcurrentSkipListSet<>(Arrays.asList(img1, img2)),
+            0.1, 0.1);
+
+    record.addCommand(cmd1);
+
+    assertEquals(0.1, img1.getMovingLatLon().lat(), 0.01);
+
+    record.undo();
+
+    assertEquals(0.0, img1.getMovingLatLon().lat(), 0.01);
+
+    record.redo();
+
+    assertEquals(0.1, img1.getMovingLatLon().lat(), 0.01);
+
+    record.addCommand(cmd2);
+    record.undo();
+
+    assertEquals(-0.1, img1.getMovingLatLon().lat(), 0.01);
+
+    record.redo();
+
+    assertEquals(0.1, img1.getMovingLatLon().lat(), 0.01);
+  }
+
+  /**
+   * Tests {@link CommandTurn} class.
+   */
+  @Test
+  public void commandTurnTest() {
+    CommandTurn cmd1 = new CommandTurn(
+            new ConcurrentSkipListSet<>(Arrays.asList(img1, img2)),
+            0.2);
+    CommandTurn cmd2 = new CommandTurn(
+            new ConcurrentSkipListSet<>(Arrays.asList(img1, img2)),
+            0.1);
+
+    record.addCommand(cmd1);
+    record.undo();
+
+    assertEquals(-0.1, img1.getMovingHe(), 0.01);
+
+    record.redo();
+
+    assertEquals(0.1, img1.getMovingHe(), 0.01);
+
+    record.addCommand(cmd2);
+    record.undo();
+
+    assertEquals(-0.2, img1.getMovingHe(), 0.01);
+
+    record.redo();
+
+    assertEquals(0.1, img1.getMovingHe(), 0.01);
+  }
+
+  /**
+   * Tests {@link CommandJoin} class.
+   */
+  @Test
+  public void commandJoinClass() {
+    CommandJoin cmd1 = new CommandJoin(img1, img2);
+    CommandJoin cmd2 = new CommandJoin(img2, img3);
+
+    record.addCommand(cmd1);
+    assertEquals(2, img1.getSequence().getImages().size());
+    assertEquals(img2, img1.next());
+    record.undo();
+    assertEquals(1, img1.getSequence().getImages().size());
+    record.redo();
+    record.addCommand(cmd2);
+    assertEquals(3, img1.getSequence().getImages().size());
+    assertEquals(img3, img1.next().next());
+  }
+
+  @Test(expected=NullPointerException.class)
+  public void commandJoinNull1() {
+    new CommandJoin(img1, null);
+  }
+
+  @Test(expected=NullPointerException.class)
+  public void commandJoinNull2() {
+    new CommandJoin(null, img1);
+  }
+
+  /**
+   * Tests {@link CommandUnjoin} class.
+   */
+  @Test
+  public void commandUnjoinClass() {
+    CommandJoin join1 = new CommandJoin(img1, img2);
+    CommandJoin join2 = new CommandJoin(img2, img3);
+
+    CommandUnjoin cmd1 = new CommandUnjoin(
+            Arrays.asList(new StreetsideAbstractImage[]{img1, img2}));
+    CommandUnjoin cmd2 = new CommandUnjoin(
+            Arrays.asList(new StreetsideAbstractImage[]{img2, img3}));
+
+    record.addCommand(join1);
+    record.addCommand(join2);
+
+    record.addCommand(cmd1);
+    assertEquals(1, img1.getSequence().getImages().size());
+    record.undo();
+    assertEquals(3, img1.getSequence().getImages().size());
+    record.redo();
+    record.addCommand(cmd2);
+    assertEquals(1, img1.getSequence().getImages().size());
+    assertEquals(1, img2.getSequence().getImages().size());
+
+    try {
+      record.addCommand(new CommandUnjoin(Arrays.asList(new StreetsideAbstractImage[]{img1, img2, img3})));
+      fail();
+    } catch (IllegalArgumentException e) {
+      // Expected output.
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/io/download/SequenceDownloadRunnableTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/io/download/SequenceDownloadRunnableTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/io/download/SequenceDownloadRunnableTest.java	(revision 34317)
@@ -0,0 +1,81 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.io.download;
+
+import static org.junit.Assert.assertEquals;
+
+import java.lang.reflect.Field;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.function.Function;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.plugins.streetside.StreetsideLayer;
+import org.openstreetmap.josm.plugins.streetside.utils.StreetsideProperties;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil.StreetsideTestRules;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+public class SequenceDownloadRunnableTest {
+
+  @Rule
+  public JOSMTestRules rules = new StreetsideTestRules().platform();
+
+  private static final Function<Bounds, URL> SEARCH_SEQUENCES_URL_GEN = b -> {
+    // TODO: modify and use Streetside URL @rrh
+    return SequenceDownloadRunnableTest.class.getResource("/api/v3/responses/searchSequences.json");
+  };
+  private Field urlGenField;
+
+  @AfterClass
+  public static void tearDown() {
+    MainApplication.getLayerManager().resetState();
+  }
+
+  // TODO: fox!
+  //@Test
+  public void testRun1() throws IllegalArgumentException, IllegalAccessException {
+    testNumberOfDecodedImages(4, SEARCH_SEQUENCES_URL_GEN, new Bounds(7.246497, 16.432955, 7.249027, 16.432976));
+  }
+
+  //TODO: fox!
+  //@Test
+  public void testRun2() throws IllegalArgumentException, IllegalAccessException {
+    testNumberOfDecodedImages(0, SEARCH_SEQUENCES_URL_GEN, new Bounds(0, 0, 0, 0));
+  }
+
+  //TODO: fox!
+ //@Test
+  public void testRun3() throws IllegalArgumentException, IllegalAccessException {
+    testNumberOfDecodedImages(0, b -> {
+      try { return new URL("https://streetside/nonexistentURL"); } catch (MalformedURLException e) { return null; }
+    }, new Bounds(0, 0, 0, 0));
+  }
+
+  //TODO: fox!
+ //@Test
+  public void testRun4() throws IllegalArgumentException, IllegalAccessException {
+    StreetsideProperties.CUT_OFF_SEQUENCES_AT_BOUNDS.put(true);
+    testNumberOfDecodedImages(4, SEARCH_SEQUENCES_URL_GEN, new Bounds(7.246497, 16.432955, 7.249027, 16.432976));
+  }
+
+  //TODO: fox!
+ //@Test
+  public void testRun5() throws IllegalArgumentException, IllegalAccessException {
+    StreetsideProperties.CUT_OFF_SEQUENCES_AT_BOUNDS.put(true);
+    testNumberOfDecodedImages(0, SEARCH_SEQUENCES_URL_GEN, new Bounds(0, 0, 0, 0));
+  }
+
+  private void testNumberOfDecodedImages(int expectedNumImgs, Function<Bounds, URL> urlGen, Bounds bounds)
+      throws IllegalArgumentException, IllegalAccessException {
+    SequenceDownloadRunnable r = new SequenceDownloadRunnable(StreetsideLayer.getInstance().getData(), bounds);
+    urlGenField.set(null, urlGen);
+    r.run();
+    assertEquals(expectedNumImgs, StreetsideLayer.getInstance().getData().getImages().size());
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/model/ImageDetectionTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/model/ImageDetectionTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/model/ImageDetectionTest.java	(revision 34317)
@@ -0,0 +1,36 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.awt.geom.Path2D;
+
+import org.junit.Test;
+
+public class ImageDetectionTest {
+  @Test
+  public void test() {
+    ImageDetection id = new ImageDetection(new Path2D.Double(), "imgKey", "key", 0.123, "packageName", "value");
+    ImageDetection trafficsign = new ImageDetection(new Path2D.Double(), "imgKey2", "key2", 4.567, "trafficsign", "value2");
+    
+    assertEquals("imgKey", id.getImageKey());
+    assertEquals("imgKey2", trafficsign.getImageKey());
+    
+    assertEquals("key", id.getKey());
+    assertEquals("key2", trafficsign.getKey());
+    
+    assertEquals("packageName", id.getPackage());
+    assertEquals("trafficsign", trafficsign.getPackage());
+    
+    assertEquals(0.123, id.getScore(), 1e-9);
+    assertEquals(4.567, trafficsign.getScore(), 1e-9);
+    
+    assertFalse(id.isTrafficSign());
+    assertTrue(trafficsign.isTrafficSign());
+    
+    assertEquals("value", id.getValue());
+    assertEquals("value2", trafficsign.getValue());
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/model/MapObjectTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/model/MapObjectTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/model/MapObjectTest.java	(revision 34317)
@@ -0,0 +1,118 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.model;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.lang.reflect.Field;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.function.Function;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil.StreetsideTestRules;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+public class MapObjectTest {
+
+  @Rule
+  public JOSMTestRules rules = new StreetsideTestRules().platform();
+
+  private static MapObject mo1;
+  private static MapObject mo2;
+  private static MapObject mo3;
+
+  private static Field iconUrlGen;
+  private static Object iconUrlGenValue;
+
+  public static void initMapObjects() {
+    mo1 = new MapObject(new LatLon(0, 0), "key1", "", "", 0, 0, 0);
+    mo2 = new MapObject(new LatLon(0, 0), "key2", "", "", 0, 0, 0);
+    mo3 = new MapObject(new LatLon(0, 0), "key1", "", "", 0, 0, 0);
+  }
+
+  @Before
+  public void setUp() throws IllegalArgumentException, IllegalAccessException {
+    initMapObjects();
+    // Sets the keys of the null-key-constants to null
+    Field keyField = TestUtil.getAccessibleField(KeyIndexedObject.class, "key");
+
+    // Replace function for generating icon URLs with one that searches the local resources for files
+    // If a resource can't be found, return an invalid URL
+    iconUrlGen = TestUtil.getAccessibleField(MapObject.class, "iconUrlGen");
+    iconUrlGenValue = iconUrlGen.get(null);
+    iconUrlGen.set(null, (Function<String, URL>) (str -> {
+      URL result = MapObject.class.getResource(str);
+      if (result != null) {
+        return result;
+      }
+      try {
+        return new URL("https://invalidURL" + str);
+      } catch (MalformedURLException e) {
+        return null;
+      }
+    }));
+  }
+
+  @After
+  public void cleanUp() throws IllegalArgumentException, IllegalAccessException {
+    iconUrlGen.set(null, iconUrlGenValue);
+  }
+
+  @SuppressWarnings({ "unused", "PMD.AvoidDuplicateLiterals" })
+  @Test(expected = IllegalArgumentException.class)
+  public void testIllArgEx1() {
+    new MapObject(new LatLon(0, 0), null, "", "", 0, 0, 0);
+  }
+
+  @SuppressWarnings("unused")
+  @Test(expected = IllegalArgumentException.class)
+  public void testIllArgEx2() {
+    new MapObject(new LatLon(0, 0), "", null, "", 0, 0, 0);
+  }
+
+  @SuppressWarnings("unused")
+  @Test(expected = IllegalArgumentException.class)
+  public void testIllArgEx3() {
+    new MapObject(new LatLon(0, 0), "", "", null, 0, 0, 0);
+  }
+
+  @SuppressWarnings("unused")
+  @Test(expected = IllegalArgumentException.class)
+  public void testIllArgEx4() {
+    new MapObject(null, "", "", "", 0, 0, 0);
+  }
+
+  @Test
+  public void testIcon() throws SecurityException, IllegalArgumentException, NoSuchFieldException, IllegalAccessException {
+    assertNotNull(MapObject.getIcon("/images/mapicon.png"));
+    assertNotNull(MapObject.getIcon("/images/mapicon.png"));
+
+    Field iconUnknownType = MapObject.class.getDeclaredField("ICON_UNKNOWN_TYPE");
+    iconUnknownType.setAccessible(true);
+    assertEquals(MapObject.getIcon("not-in-set"), iconUnknownType.get(null));
+  }
+
+  @Test
+  public void testInvalidIconDownloadURL() throws IllegalArgumentException, IllegalAccessException {
+    assertEquals(TestUtil.getAccessibleField(MapObject.class, "ICON_UNKNOWN_TYPE").get(null), MapObject.getIcon("/invalidPathToIcon"));
+  }
+
+  @Test
+  public void testEquals() throws SecurityException, IllegalArgumentException {
+    assertEquals(mo1, mo1);
+    assertNotEquals(mo1, null);
+    assertNotEquals(mo1, "");
+    assertNotEquals(mo1, mo2);
+    assertEquals(mo1, mo3);
+    assertEquals(mo1.hashCode(), mo3.hashCode());
+  }
+
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/oauth/OAuthPortListenerTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/oauth/OAuthPortListenerTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/oauth/OAuthPortListenerTest.java	(revision 34317)
@@ -0,0 +1,38 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.oauth;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+
+import org.junit.Test;
+
+/**
+ * Tests the {@link OAuthPortListener} class.
+ *
+ * @author nokutu
+ * @see OAuthPortListener
+ *
+ */
+public class OAuthPortListenerTest {
+
+  /**
+   * Test that the threads responds when the browser makes the request.
+   */
+  @Test
+  public void responseTest() throws IOException, InterruptedException {
+    OAuthPortListener t = new OAuthPortListener(null);
+    t.start();
+    Thread.sleep(500);
+    URL url = new URL("http://localhost:"+OAuthPortListener.PORT+"?access_token=access_token");
+    HttpURLConnection con = (HttpURLConnection) url.openConnection();
+    BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream(), StandardCharsets.UTF_8));
+    in.readLine();
+    assertEquals(OAuthPortListener.RESPONSE, in.readLine());
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/ImageUtilTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/ImageUtilTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/ImageUtilTest.java	(revision 34317)
@@ -0,0 +1,32 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import static org.junit.Assert.assertEquals;
+
+import java.awt.image.BufferedImage;
+
+import javax.swing.ImageIcon;
+
+import org.junit.Test;
+
+public class ImageUtilTest {
+
+  @Test
+  public void testUtilityClass() {
+    TestUtil.testUtilityClass(ImageUtil.class);
+  }
+
+  @Test
+  public void testScaleImageIcon() {
+    ImageIcon largeLandscape = new ImageIcon(new BufferedImage(72, 60, BufferedImage.TYPE_4BYTE_ABGR));
+    ImageIcon largePortrait = new ImageIcon(new BufferedImage(56, 88, BufferedImage.TYPE_4BYTE_ABGR));
+    ImageIcon smallLandscape = ImageUtil.scaleImageIcon(largeLandscape, 24);
+    ImageIcon smallPortrait = ImageUtil.scaleImageIcon(largePortrait, 22);
+
+    assertEquals(24, smallLandscape.getIconWidth());
+    assertEquals(20, smallLandscape.getIconHeight());
+
+    assertEquals(22, smallPortrait.getIconHeight());
+    assertEquals(14, smallPortrait.getIconWidth());
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/JsonUtil.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/JsonUtil.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/JsonUtil.java	(revision 34317)
@@ -0,0 +1,18 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+
+import javax.json.Json;
+import javax.json.JsonObject;
+
+public final class JsonUtil {
+  private JsonUtil() {
+    // Private constructor to avoid instantiation
+  }
+
+  public static JsonObject string2jsonObject(String s) {
+    return Json.createReader(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8))).readObject();
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/PluginStateTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/PluginStateTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/PluginStateTest.java	(revision 34317)
@@ -0,0 +1,53 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import org.openstreetmap.josm.Main;
+
+/**
+ * Tests {@link PluginState} class.
+ *
+ * @author nokutu
+ * @see PluginState
+ */
+public class PluginStateTest {
+
+  /**
+   * Test the methods related to the download.
+   */
+  @Test
+  public void downloadTest() {
+    assertEquals(false, PluginState.isDownloading());
+    PluginState.startDownload();
+    assertEquals(true, PluginState.isDownloading());
+    PluginState.startDownload();
+    assertEquals(true, PluginState.isDownloading());
+    PluginState.finishDownload();
+    assertEquals(true, PluginState.isDownloading());
+    PluginState.finishDownload();
+    assertEquals(false, PluginState.isDownloading());
+  }
+
+  /**
+   * Tests the methods related to the upload.
+   */
+  @Test
+  public void uploadTest() {
+    Main.main = null;
+    assertEquals(false, PluginState.isUploading());
+    PluginState.addImagesToUpload(2);
+    assertEquals(2, PluginState.getImagesToUpload());
+    assertEquals(0, PluginState.getImagesUploaded());
+    assertEquals(true, PluginState.isUploading());
+    PluginState.imageUploaded();
+    assertEquals(1, PluginState.getImagesUploaded());
+    assertEquals(true, PluginState.isUploading());
+    PluginState.imageUploaded();
+    assertEquals(false, PluginState.isUploading());
+    assertEquals(2, PluginState.getImagesToUpload());
+    assertEquals(2, PluginState.getImagesUploaded());
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideColorSchemeTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideColorSchemeTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideColorSchemeTest.java	(revision 34317)
@@ -0,0 +1,20 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import javax.swing.JComponent;
+
+import org.junit.Test;
+
+public class StreetsideColorSchemeTest {
+
+  @Test
+  public void testUtilityClass() {
+    TestUtil.testUtilityClass(StreetsideColorScheme.class);
+  }
+
+  @Test
+  public void testStyleAsDefaultPanel() {
+    StreetsideColorScheme.styleAsDefaultPanel();
+    StreetsideColorScheme.styleAsDefaultPanel((JComponent[]) null);
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsidePropertiesTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsidePropertiesTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsidePropertiesTest.java	(revision 34317)
@@ -0,0 +1,20 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil.StreetsideTestRules;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+public class StreetsidePropertiesTest {
+
+  @Rule
+  public JOSMTestRules rules = new StreetsideTestRules();
+
+  @Test
+  public void test() {
+    TestUtil.testUtilityClass(StreetsideProperties.class);
+  }
+
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideURLTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideURLTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideURLTest.java	(revision 34317)
@@ -0,0 +1,179 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class StreetsideURLTest {
+  // TODO: replace with Streetside URL @rrh
+  private static final String CLIENT_ID_QUERY_PART = "client_id=T1Fzd20xZjdtR0s1VDk5OFNIOXpYdzoxNDYyOGRkYzUyYTFiMzgz";
+
+  public static class APIv3 {
+
+    @Ignore
+	@Test
+    public void testSearchDetections() {
+      assertUrlEquals(StreetsideURL.APIv3.searchDetections(null), "https://a.streetside.com/v3/detections", CLIENT_ID_QUERY_PART);
+    }
+
+    @Ignore
+    @Test
+    public void testSearchImages() {
+      assertUrlEquals(StreetsideURL.APIv3.searchImages(null), "https://a.streetside.com/v3/images", CLIENT_ID_QUERY_PART);
+    }
+
+    @Ignore
+    @Test
+    public void testSubmitChangeset() throws MalformedURLException {
+      assertEquals(
+        new URL("https://a.streetside.com/v3/changesets?" + CLIENT_ID_QUERY_PART),
+        StreetsideURL.APIv3.submitChangeset()
+      );
+    }
+
+    @Test
+    public void testParseNextFromHeaderValue() throws MalformedURLException {
+      String headerVal =
+        "<https://a.streetside.com/v3/sequences?page=1&per_page=200&client_id=TG1sUUxGQlBiYWx2V05NM0pQNUVMQTo2NTU3NTBiNTk1NzM1Y2U2>; rel=\"first\", " +
+        "<https://a.streetside.com/v3/sequences?page=2&per_page=200&client_id=TG1sUUxGQlBiYWx2V05NM0pQNUVMQTo2NTU3NTBiNTk1NzM1Y2U2>; rel=\"prev\", " +
+        "<https://a.streetside.com/v3/sequences?page=4&per_page=200&client_id=TG1sUUxGQlBiYWx2V05NM0pQNUVMQTo2NTU3NTBiNTk1NzM1Y2U2>; rel=\"next\"";
+      assertEquals(
+        new URL("https://a.streetside.com/v3/sequences?page=4&per_page=200&client_id=TG1sUUxGQlBiYWx2V05NM0pQNUVMQTo2NTU3NTBiNTk1NzM1Y2U2"),
+        StreetsideURL.APIv3.parseNextFromLinkHeaderValue(headerVal)
+      );
+    }
+
+    @Test
+    public void testParseNextFromHeaderValue2() throws MalformedURLException {
+      String headerVal =
+        "<https://urlFirst>; rel=\"first\", " +
+        "rel = \"next\" ; < ; , " +
+        "rel = \"next\" ; <https://urlNext> , " +
+        "<https://urlPrev>; rel=\"prev\"";
+      assertEquals(new URL("https://urlNext"), StreetsideURL.APIv3.parseNextFromLinkHeaderValue(headerVal));
+    }
+
+    @Test
+    public void testParseNextFromHeaderValueNull() {
+      assertEquals(null, StreetsideURL.APIv3.parseNextFromLinkHeaderValue(null));
+    }
+
+    @Test
+    public void testParseNextFromHeaderValueMalformed() {
+      assertEquals(null, StreetsideURL.APIv3.parseNextFromLinkHeaderValue("<###>; rel=\"next\", blub"));
+    }
+  }
+
+  public static class Cloudfront {
+    @Ignore
+	@Test
+    public void testThumbnail() {
+      assertUrlEquals(StreetsideURL.VirtualEarth.streetsideTile("arbitrary_key", true), "https://d1cuyjsrcm0gby.cloudfront.net/arbitrary_key/thumb-2048.jpg");
+      assertUrlEquals(StreetsideURL.VirtualEarth.streetsideTile("arbitrary_key2", false), "https://d1cuyjsrcm0gby.cloudfront.net/arbitrary_key2/thumb-320.jpg");
+    }
+  }
+
+  @Ignore
+  @Test
+  public void testBrowseImageURL() throws MalformedURLException {
+    assertEquals(
+        new URL("https://www.streetside.com/map/im/1234567890123456789012"),
+        StreetsideURL.MainWebsite.browseImage("1234567890123456789012")
+    );
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testIllegalBrowseImageURL() {
+    StreetsideURL.MainWebsite.browseImage(null);
+  }
+
+  @Ignore
+  @Test
+  public void testConnectURL() {
+    assertUrlEquals(
+        StreetsideURL.MainWebsite.connect("http://redirect-host/ä"),
+        "https://www.streetside.com/connect",
+        CLIENT_ID_QUERY_PART,
+        "scope=user%3Aread+public%3Aupload+public%3Awrite",
+        "response_type=token",
+        "redirect_uri=http%3A%2F%2Fredirect-host%2F%C3%A4"
+    );
+
+    assertUrlEquals(
+        StreetsideURL.MainWebsite.connect(null),
+        "https://www.streetside.com/connect",
+        CLIENT_ID_QUERY_PART,
+        "scope=user%3Aread+public%3Aupload+public%3Awrite",
+        "response_type=token"
+    );
+
+    assertUrlEquals(
+        StreetsideURL.MainWebsite.connect(""),
+        "https://www.streetside.com/connect",
+        CLIENT_ID_QUERY_PART,
+        "scope=user%3Aread+public%3Aupload+public%3Awrite",
+        "response_type=token"
+    );
+  }
+
+  @Ignore
+  @Test
+  public void testUploadSecretsURL() throws MalformedURLException {
+    assertEquals(
+        new URL("https://a.streetside.com/v2/me/uploads/secrets?"+CLIENT_ID_QUERY_PART),
+        StreetsideURL.uploadSecretsURL()
+    );
+  }
+
+  @Ignore
+  @Test
+  public void testUserURL() throws MalformedURLException {
+    assertEquals(
+        new URL("https://a.streetside.com/v3/me?"+CLIENT_ID_QUERY_PART),
+        StreetsideURL.APIv3.userURL()
+    );
+  }
+
+  @Test
+  public void testString2MalformedURL()
+      throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+    Method method = StreetsideURL.class.getDeclaredMethod("string2URL", String[].class);
+    method.setAccessible(true);
+    assertNull(method.invoke(null, new Object[]{new String[]{"malformed URL"}})); // this simply invokes string2URL("malformed URL")
+    assertNull(method.invoke(null, new Object[]{null})); // invokes string2URL(null)
+  }
+
+  @Test
+  public void testUtilityClass() {
+    TestUtil.testUtilityClass(StreetsideURL.class);
+    TestUtil.testUtilityClass(StreetsideURL.APIv3.class);
+    TestUtil.testUtilityClass(StreetsideURL.VirtualEarth.class);
+    TestUtil.testUtilityClass(StreetsideURL.MainWebsite.class);
+  }
+
+  private static void assertUrlEquals(URL actualUrl, String expectedBaseUrl, String... expectedParams) {
+    final String actualUrlString = actualUrl.toString();
+    assertEquals(expectedBaseUrl, actualUrlString.contains("?") ? actualUrlString.substring(0, actualUrlString.indexOf('?')) : actualUrlString);
+    String[] actualParams = actualUrl.getQuery() == null ? new String[0] : actualUrl.getQuery().split("&");
+    assertEquals(expectedParams.length, actualParams.length);
+    for (int exIndex = 0; exIndex < expectedParams.length; exIndex++) {
+      boolean parameterIsPresent = false;
+      for (int acIndex = 0; !parameterIsPresent && acIndex < actualParams.length; acIndex++) {
+        parameterIsPresent |= actualParams[acIndex].equals(expectedParams[exIndex]);
+      }
+      assertTrue(
+          expectedParams[exIndex] + " was expected in the query string of " + actualUrl.toString() + " but wasn't there.",
+          parameterIsPresent
+      );
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideUtilsTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideUtilsTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/StreetsideUtilsTest.java	(revision 34317)
@@ -0,0 +1,43 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.commons.imaging.common.RationalNumber;
+import org.apache.commons.imaging.formats.tiff.constants.GpsTagConstants;
+import org.junit.Test;
+
+/**
+ * Tests the static methods of the class {@link StreetsideUtils}
+ *
+ * @see StreetsideUtils
+ * @author nokutu
+ *
+ */
+public class StreetsideUtilsTest {
+
+  @Test
+  public void testUtilityClass() {
+    TestUtil.testUtilityClass(StreetsideUtils.class);
+  }
+
+  /**
+   * Test {@link StreetsideUtils#degMinSecToDouble(RationalNumber[], String)}
+   * method.
+   */
+  @Test
+  public void degMinSecToDoubleTest() {
+    RationalNumber[] num = new RationalNumber[3];
+    num[0] = new RationalNumber(1, 1);
+    num[1] = new RationalNumber(0, 1);
+    num[2] = new RationalNumber(0, 1);
+    String ref = GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF_VALUE_NORTH;
+    assertEquals(1, StreetsideUtils.degMinSecToDouble(num, ref), 0.01);
+    ref = GpsTagConstants.GPS_TAG_GPS_LATITUDE_REF_VALUE_SOUTH;
+    assertEquals(-1, StreetsideUtils.degMinSecToDouble(num, ref), 0.01);
+    num[0] = new RationalNumber(180, 1);
+    assertEquals(-180, StreetsideUtils.degMinSecToDouble(num, ref), 0.01);
+    num[0] = new RationalNumber(190, 1);
+    assertEquals(170, StreetsideUtils.degMinSecToDouble(num, ref), 0.01);
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/TestUtil.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/TestUtil.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/TestUtil.java	(revision 34317)
@@ -0,0 +1,97 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.awt.GraphicsEnvironment;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.logging.Level;
+
+import org.junit.runners.model.InitializationError;
+
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.Utils;
+
+/**
+ * Utilities for tests.
+ */
+public final class TestUtil {
+
+  private TestUtil() {
+    // Prevent instantiation
+  }
+
+  public static Field getAccessibleField(Class<?> clazz, String fieldName) {
+    try {
+      Field result = clazz.getDeclaredField(fieldName);
+      result.setAccessible(true);
+      Field modifiers = Field.class.getDeclaredField("modifiers");
+      modifiers.setAccessible(true);
+      modifiers.setInt(result, modifiers.getInt(result) & ~Modifier.FINAL);
+      return result;
+    } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
+      fail(e.getLocalizedMessage());
+    }
+    return null;
+  }
+
+  /**
+   * Helper method for obtaining the value of a private field
+   * @param object the object of which you want the private field
+   * @param name the name of the private field
+   * @return the current value that field has
+   */
+  public static Object getPrivateFieldValue(Object object, String name) {
+    try {
+      return getAccessibleField(object.getClass(), name).get(object);
+    } catch (IllegalAccessException | SecurityException e) {
+      fail(e.getLocalizedMessage());
+    }
+    return null;
+  }
+
+  /**
+   * This method tests utility classes for common coding standards (exactly one constructor that's private,
+   * only static methods, …) and fails the current test if one of those standards is not met.
+   * This is inspired by <a href="https://stackoverflow.com/a/10872497">an answer on StackOverflow.com</a> .
+   * @param c the class under test
+   */
+  public static void testUtilityClass(final Class<?> c) {
+    try {
+      // class must be final
+      assertTrue(Modifier.isFinal(c.getModifiers()));
+      // with exactly one constructor
+      assertEquals(1, c.getDeclaredConstructors().length);
+      final Constructor<?> constructor = c.getDeclaredConstructors()[0];
+      // constructor has to be private
+      assertTrue(!constructor.isAccessible() && Modifier.isPrivate(constructor.getModifiers()));
+      constructor.setAccessible(true);
+      // Call private constructor for code coverage
+      constructor.newInstance();
+      for (Method m : c.getMethods()) {
+        // Check if all methods are static
+        assertTrue(m.getDeclaringClass() != c || Modifier.isStatic(m.getModifiers()));
+      }
+    } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+      fail(e.getLocalizedMessage());
+    }
+  }
+
+  public static class StreetsideTestRules extends JOSMTestRules {
+    @Override
+    protected void before() throws InitializationError, ReflectiveOperationException {
+      Logging.getLogger().setFilter(record -> record.getLevel().intValue() >= Level.WARNING.intValue() || record.getSourceClassName().startsWith("org.openstreetmap.josm.plugins.streetside"));
+      Utils.updateSystemProperty("java.util.logging.SimpleFormatter.format", "%1$tF %1$tT.%1$tL %2$s %4$s: %5$s%6$s%n");
+      final String isHeadless = Boolean.toString(GraphicsEnvironment.isHeadless());
+      super.before();
+      System.setProperty("java.awt.headless", isHeadless);
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonDecoderTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonDecoderTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonDecoderTest.java	(revision 34317)
@@ -0,0 +1,35 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils.api;
+
+import static org.junit.Assert.assertNull;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.function.Function;
+
+import javax.json.Json;
+import javax.json.JsonObject;
+
+import org.junit.Test;
+
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil;
+
+public class JsonDecoderTest {
+
+  @Test
+  public void testUtilityClass() {
+    TestUtil.testUtilityClass(JsonDecoder.class);
+  }
+
+  @Test
+  public void testDecodeDoublePair() {
+    assertNull(JsonDecoder.decodeDoublePair(null));
+  }
+
+  static void assertDecodesToNull(Function<JsonObject, ?> function, String...parts) {
+    assertNull(function.apply(
+      Json.createReader(new ByteArrayInputStream(String.join(" ", parts).getBytes(StandardCharsets.UTF_8))).readObject()
+    ));
+  }
+
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonImageDetailsDecoderTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonImageDetailsDecoderTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonImageDetailsDecoderTest.java	(revision 34317)
@@ -0,0 +1,101 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils.api;
+
+import static org.junit.Assert.assertEquals;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+import javax.json.Json;
+import javax.json.JsonObject;
+
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.StreetsideAbstractImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideData;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImportedImage;
+import org.openstreetmap.josm.plugins.streetside.cubemap.CubemapUtils;
+import org.openstreetmap.josm.plugins.streetside.utils.JsonUtil;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil.StreetsideTestRules;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+public class JsonImageDetailsDecoderTest {
+
+  @Rule
+  public JOSMTestRules rules = new StreetsideTestRules().platform().preferences();
+
+  @Test
+  public void testUtilityClass() {
+    TestUtil.testUtilityClass(JsonImageDetailsDecoder.class);
+  }
+
+  @Ignore
+  @Test
+  public void testDecodeImageInfos() {
+    JsonObject searchImagesResponse = Json.createReader(
+      JsonImageDetailsDecoderTest.class.getResourceAsStream("/api/v3/responses/searchImages.json")
+    ).readObject();
+    StreetsideData data = new StreetsideDataMock();
+    StreetsideImage img1 = new StreetsideImage("_yA5uXuSNugmsK5VucU6Bg", new LatLon(0, 0), 0);
+    StreetsideImage img2 = new StreetsideImage("nmF-Wq4EvVTgAUmBicSCCg", new LatLon(0, 0), 0);
+    StreetsideImage img3 = new StreetsideImage("arbitrary_key", new LatLon(0, 0), 0);
+    StreetsideAbstractImage img4 = new StreetsideImportedImage(CubemapUtils.IMPORTED_ID, new LatLon(0, 0), 0, null);
+    img4.setHe(0);
+    data.add(img1);
+    data.add(img2);
+    data.add(img3);
+    data.add(img4);
+    JsonImageDetailsDecoder.decodeImageInfos(searchImagesResponse, data);
+    assertEquals(1_491_803_490_334L, img1.getHe()); // 2017-04-10T05:51:30.334Z
+    assertEquals(1_491_803_486_853L, img2.getHe()); // 2017-04-10T05:51:26.853Z
+    assertEquals(0L, img3.getHe());
+    assertEquals(0L, img4.getHe());
+  }
+
+  @Test
+  public void testInvalidImageInfos() {
+    StreetsideDataMock data = new StreetsideDataMock();
+    JsonImageDetailsDecoder.decodeImageInfos(null, data);
+    JsonImageDetailsDecoder.decodeImageInfos(JsonUtil.string2jsonObject("{}"), null);
+    JsonImageDetailsDecoder.decodeImageInfos(JsonUtil.string2jsonObject("{}"), data);
+    JsonImageDetailsDecoder.decodeImageInfos(JsonUtil.string2jsonObject("{\"type\":\"FeatureCollection\", \"features\":0}"), data);
+    JsonImageDetailsDecoder.decodeImageInfos(JsonUtil.string2jsonObject("{\"type\":\"FeatureCollection\", \"features\":[0, null]}"), data);
+    assertEquals(0, data.getNumImageRerievals());
+  }
+
+  @Test
+  public void testInvalidImageInfo() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+    Method decodeImageInfo = JsonImageDetailsDecoder.class.getDeclaredMethod("decodeImageInfo", JsonObject.class, StreetsideData.class);
+    StreetsideDataMock data = new StreetsideDataMock();
+    decodeImageInfo.setAccessible(true);
+    decodeImageInfo.invoke(null, null, data);
+    decodeImageInfo.invoke(null, JsonUtil.string2jsonObject("{}"), null);
+    decodeImageInfo.invoke(null, JsonUtil.string2jsonObject("{\"properties\":null}"), data);
+    decodeImageInfo.invoke(null, JsonUtil.string2jsonObject("{\"properties\":{}}"), data);
+    decodeImageInfo.invoke(null, JsonUtil.string2jsonObject("{\"properties\":{\"key\":\"arbitrary_key\"}}"), data);
+    assertEquals(0, data.getNumImageRerievals());
+  }
+
+  private static class StreetsideDataMock extends StreetsideData {
+    private int imageRetrievals;
+
+    /**
+     * Returns how often the method {@link #getImages()} has been accessed for this instance.
+     * @return
+     */
+    public int getNumImageRerievals() {
+      return imageRetrievals;
+    }
+
+    @Override
+    public Set<StreetsideAbstractImage> getImages() {
+      imageRetrievals++;
+      return super.getImages();
+    }
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonImageDetectionDecoderTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonImageDetectionDecoderTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonImageDetectionDecoderTest.java	(revision 34317)
@@ -0,0 +1,201 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import static org.openstreetmap.josm.plugins.streetside.utils.api.JsonDecoderTest.assertDecodesToNull;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.PathIterator;
+import java.io.ByteArrayInputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonValue;
+
+import org.junit.Test;
+
+import org.openstreetmap.josm.plugins.streetside.model.ImageDetection;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil;
+
+public class JsonImageDetectionDecoderTest {
+
+  @Test
+  public void testDecodeImageDetections() {
+    final Collection<ImageDetection> decodeResult = JsonDecoder.decodeFeatureCollection(
+      Json.createReader(this.getClass().getResourceAsStream("/api/v3/responses/searchImageDetections.json")).readObject(),
+      JsonImageDetectionDecoder::decodeImageDetection
+    );
+
+    assertNotNull(decodeResult);
+    assertEquals(2, decodeResult.size());
+
+    // Keep in mind, that no particular order is enforced for the decoded result.
+    // That's why the entries of the collection are put into a Map, so that we can refer to the entries by key.
+    final Iterator<ImageDetection> it = decodeResult.iterator();
+    HashMap<String, ImageDetection> detections = new HashMap<>();
+    while (it.hasNext()) {
+      final ImageDetection detection = it.next();
+      detections.put(detection.getKey(), detection);
+    }
+
+    final ImageDetection id1 = detections.get("bzqdn10wz1s1xd3lae3hawgja0");
+    assertEquals("33zgql54_tBVvmIij0zrcA", id1.getImageKey());
+    assertEquals("bzqdn10wz1s1xd3lae3hawgja0", id1.getKey());
+    assertEquals(0.000001, id1.getScore(), 1e-9);
+    assertEquals("information--pedestrians-crossing--g1", id1.getValue());
+
+    final PathIterator pi1 = id1.getShape().getPathIterator(new AffineTransform());
+    testPathSegment(pi1, PathIterator.SEG_MOVETO, 0.42724609375, 0.69091796875);
+    testPathSegment(pi1, PathIterator.SEG_LINETO, 0.436279296875, 0.69091796875);
+    testPathSegment(pi1, PathIterator.SEG_LINETO, 0.436279296875, 0.70263671875);
+    testPathSegment(pi1, PathIterator.SEG_LINETO, 0.42724609375, 0.70263671875);
+    testPathSegment(pi1, PathIterator.SEG_LINETO, 0.42724609375, 0.69091796875);
+    testPathSegment(pi1, PathIterator.SEG_CLOSE, 0, 0);
+
+    final ImageDetection id2 = detections.get("uzve1xkyk5qbjwrzaq0do09u1x");
+    assertEquals("33zgql54_tBVvmIij0zrcA", id2.getImageKey());
+    assertEquals("uzve1xkyk5qbjwrzaq0do09u1x", id2.getKey());
+    assertEquals(0.000001, id2.getScore(), 1e-9);
+    assertEquals("information--pedestrians-crossing--g1", id2.getValue());
+
+    final PathIterator pi2 = id2.getShape().getPathIterator(new AffineTransform());
+    testPathSegment(pi2, PathIterator.SEG_MOVETO, 0.42724609375, 0.69091796875);
+    testPathSegment(pi2, PathIterator.SEG_LINETO, 0.436279296875, 0.69091796875);
+    testPathSegment(pi2, PathIterator.SEG_LINETO, 0.436279296875, 0.70263671875);
+    testPathSegment(pi2, PathIterator.SEG_LINETO, 0.42724609375, 0.70263671875);
+    testPathSegment(pi2, PathIterator.SEG_LINETO, 0.42724609375, 0.69091796875);
+    testPathSegment(pi2, PathIterator.SEG_CLOSE, 0, 0);
+  }
+
+  @Test
+  public void testDecodeImageDetection() {
+    final ImageDetection decodeResult = JsonImageDetectionDecoder.decodeImageDetection(
+      Json.createReader(this.getClass().getResourceAsStream("/api/v3/responses/imageDetection.json")).readObject()
+    );
+
+    assertNotNull(decodeResult);
+    assertEquals("QhRcdlGS_Rn_a1_HTclefg", decodeResult.getImageKey());
+    assertEquals("gn0llgitnnuqonecevbmf52ino", decodeResult.getKey());
+    assertEquals("trafficsign", decodeResult.getPackage());
+    assertTrue(decodeResult.isTrafficSign());
+    assertEquals(0.710661225175, decodeResult.getScore(), 1e-9);
+    assertEquals("regulatory--no-overtaking-by-heavy-goods-vehicles--g1", decodeResult.getValue());
+
+    final PathIterator pi = decodeResult.getShape().getPathIterator(new AffineTransform());
+    testPathSegment(pi, PathIterator.SEG_MOVETO, 0.330078125, 0.466064453125);
+    testPathSegment(pi, PathIterator.SEG_LINETO, 0.3642578125, 0.466064453125);
+    testPathSegment(pi, PathIterator.SEG_LINETO, 0.3642578125, 0.51171875);
+    testPathSegment(pi, PathIterator.SEG_LINETO, 0.330078125, 0.51171875);
+    testPathSegment(pi, PathIterator.SEG_LINETO, 0.330078125, 0.466064453125);
+    testPathSegment(pi, PathIterator.SEG_CLOSE, 0, 0);
+    assertTrue(pi.isDone());
+  }
+
+  private static void testPathSegment(final PathIterator it, final int expSegmentType, final double x, final double y) {
+    final double[] segmentData = new double[6];
+    final int actualSegmentType = it.currentSegment(segmentData);
+    assertFalse(it.isDone());
+    assertEquals(expSegmentType, actualSegmentType);
+    assertEquals(x, segmentData[0], 1e-9);
+    assertEquals(y, segmentData[1], 1e-9);
+    assertEquals(0, segmentData[2], 1e-9);
+    assertEquals(0, segmentData[3], 1e-9);
+    assertEquals(0, segmentData[4], 1e-9);
+    assertEquals(0, segmentData[5], 1e-9);
+    it.next();
+  }
+
+  @Test
+  public void testImageDetectionInvalid() {
+    // null input
+    assertNull(JsonImageDetectionDecoder.decodeImageDetection(null));
+    // invalid type is set
+    assertDecodesToNull(JsonImageDetectionDecoder::decodeImageDetection, "{\"type\":\"ItsABugNotA\"}");
+    // `properties` key is not set
+    assertDecodesToNull(JsonImageDetectionDecoder::decodeImageDetection, "{\"type\": \"Feature\"}");
+    // invalid score value
+    assertDecodesToNull(
+      JsonImageDetectionDecoder::decodeImageDetection,
+      "{\"type\": \"Feature\", \"properties\":{\"score\":\"invalidScoreValue\"}}"
+    );
+    // Different properties missing
+    assertDecodesToNull(
+      JsonImageDetectionDecoder::decodeImageDetection,
+      "{\"type\": \"Feature\", \"properties\":{\"shape\":{\"type\":\"Polygon\", \"coordinates\":[[[0,0], [0,1]]]}}}"
+    );
+    assertDecodesToNull(
+      JsonImageDetectionDecoder::decodeImageDetection,
+      "{\"type\": \"Feature\", \"properties\":{\"image_key\":\"the_image_key\",",
+      "\"shape\":{\"type\":\"Polygon\", \"coordinates\":[[[0,0], [0,1]]]}}}"
+    );
+    assertDecodesToNull(
+      JsonImageDetectionDecoder::decodeImageDetection,
+      "{\"type\": \"Feature\", \"properties\":{\"image_key\":\"the_image_key\",\"key\": \"detection_key\",",
+      "\"shape\":{\"type\":\"Polygon\", \"coordinates\":[[[0,0], [0,1]]]}}}"
+    );
+    assertDecodesToNull(
+      JsonImageDetectionDecoder::decodeImageDetection,
+      "{\"type\": \"Feature\", \"properties\":{\"image_key\":\"the_image_key\",\"key\": \"detection_key\",",
+      "\"score\":314159e-5, \"shape\":{\"type\":\"Polygon\", \"coordinates\":[[[0,0], [0,1]]]}}}"
+    );
+    assertDecodesToNull(
+      JsonImageDetectionDecoder::decodeImageDetection,
+      "{\"type\": \"Feature\", \"properties\":{\"image_key\":\"the_image_key\",\"key\": \"detection_key\",",
+      "\"score\":314159e-5, \"package\":\"arbitrary_package\", \"shape\":{\"type\":\"Polygon\", \"coordinates\":[[[0,0], [0,1]]]}}}"
+    );
+  }
+
+  @Test
+  public void testDecodePolygon() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+    Method decodePolygon = JsonImageDetectionDecoder.class.getDeclaredMethod("decodePolygon", JsonArray.class);
+    decodePolygon.setAccessible(true);
+    assertNull(decodePolygon.invoke(
+      null,
+      Json.createReader(new ByteArrayInputStream("[\"notAnArray\"]".getBytes(StandardCharsets.UTF_8))).readArray()
+    ));
+  }
+
+  @Test
+  public void testDecodeShape() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+    Method decodeShape = JsonImageDetectionDecoder.class.getDeclaredMethod("decodeShape", JsonValue.class);
+    decodeShape.setAccessible(true);
+    assertNull(decodeShape.invoke(
+      null,
+      Json.createReader(new ByteArrayInputStream("{\"type\":\"Point\"}".getBytes(StandardCharsets.UTF_8))).readObject()
+    ));
+    assertNull(decodeShape.invoke(
+      null,
+      Json.createReader(new ByteArrayInputStream("{\"type\":\"Polygon\"}".getBytes(StandardCharsets.UTF_8))).readObject()
+    ));
+    assertNull(decodeShape.invoke(
+      null,
+      Json.createReader(new ByteArrayInputStream("{\"type\":\"Polygon\", \"coordinates\":[]}".getBytes(StandardCharsets.UTF_8))).readObject()
+    ));
+  }
+
+  @Test
+  public void testDecodeSimpleShape() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+    Method decodeSimplePolygon = JsonImageDetectionDecoder.class.getDeclaredMethod("decodeSimplePolygon", JsonArray.class);
+    decodeSimplePolygon.setAccessible(true);
+    assertNull(decodeSimplePolygon.invoke(
+      null,
+      Json.createReader(new ByteArrayInputStream("[\"notAnArray\"]".getBytes(StandardCharsets.UTF_8))).readArray()
+    ));
+  }
+
+  @Test
+  public void testUtilityClass() {
+    TestUtil.testUtilityClass(JsonImageDetectionDecoder.class);
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonMapObjectDecoderTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonMapObjectDecoderTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonMapObjectDecoderTest.java	(revision 34317)
@@ -0,0 +1,98 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+
+import javax.json.Json;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.model.MapObject;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil.StreetsideTestRules;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+public class JsonMapObjectDecoderTest {
+
+  @Rule
+  public JOSMTestRules rules = new StreetsideTestRules().platform();
+
+  @Test
+  public void testDecodeMapObjects() {
+    Collection<MapObject> exampleMapObjects = JsonDecoder.decodeFeatureCollection(
+      Json.createReader(this.getClass().getResourceAsStream("/api/v3/responses/searchMapObjects.json")).readObject(),
+      JsonMapObjectDecoder::decodeMapObject
+    );
+    assertEquals(1, exampleMapObjects.size());
+
+    MapObject exampleMapObject = exampleMapObjects.iterator().next();
+
+    assertEquals(1_476_610_976_060L, exampleMapObject.getFirstSeenTime()); // 2016-10-16T09:42:56.060 UTC
+    assertEquals(1_476_610_976_060L, exampleMapObject.getLastSeenTime()); // 2016-10-16T09:42:56.060 UTC
+    assertEquals(1_480_422_082_275L, exampleMapObject.getUpdatedTime()); // 2016-11-29T12:21:22.275 UTC
+    assertEquals("trafficsign", exampleMapObject.getPackage());
+    assertEquals("regulatory--no-parking--g1", exampleMapObject.getValue());
+    assertEquals("qpku21qv8rjn7fll1v671732th", exampleMapObject.getKey());
+    assertEquals(new LatLon(55.608367919921875, 13.005650520324707), exampleMapObject.getCoordinate());
+  }
+
+  @Test
+  public void testDecodeMapObject() {
+    MapObject exampleMapObject = JsonMapObjectDecoder.decodeMapObject(
+      Json.createReader(this.getClass().getResourceAsStream("/api/v3/responses/mapObject.json")).readObject()
+    );
+    assertNotNull(exampleMapObject);
+    assertEquals("9f3tl0z2xanom2inyyks65negx", exampleMapObject.getKey());
+    assertEquals("trafficsign", exampleMapObject.getPackage());
+    assertEquals("regulatory--no-entry--g1", exampleMapObject.getValue());
+    assertEquals(1_467_377_348_553L, exampleMapObject.getLastSeenTime()); // 2016-07-01T12:49:08.553 UTC
+    assertEquals(1_467_377_348_553L, exampleMapObject.getFirstSeenTime()); // 2016-07-01T12:49:08.553 UTC
+    assertEquals(1_486_566_123_778L, exampleMapObject.getUpdatedTime()); // 2017-02-08T15:02:03.778 UTC
+  }
+
+  @Test
+  public void testDecodeMapObjectInvalid() {
+    assertNull(JsonMapObjectDecoder.decodeMapObject(null));
+    assertNull(JsonMapObjectDecoder.decodeMapObject(Json.createReader(new ByteArrayInputStream("{}".getBytes(StandardCharsets.UTF_8))).readObject()));
+    assertMapObjectInvalid("{\"type\":\"Feature\", \"geometry\":{}}");
+    assertMapObjectInvalid("{\"type\":\"Feature\", \"properties\":{}}");
+    assertMapObjectInvalid("{\"type\":\"Feature\", \"geometry\":{ \"type\":\"bla\"}, \"properties\":{}}");
+    assertMapObjectInvalid("{\"type\":\"Feature\", \"geometry\":{}, \"properties\":{\"key\":\"a\"}}");
+    assertMapObjectInvalid("{\"type\":\"Feature\", \"geometry\":{}, \"properties\":{\"key\":\"a\", \"package\":\"b\"}}");
+    assertMapObjectInvalid(
+      "{\"type\":\"Feature\", \"geometry\":{}, \"properties\":{\"key\":\"a\", \"package\":\"b\", \"value\":\"c\"}}"
+    );
+    assertMapObjectInvalid(
+      "{\"type\":\"Feature\", \"geometry\":{}, \"properties\":{\"key\":\"a\", \"package\":\"b\", " +
+      "\"value\":\"c\", \"first_seen_at\":\"1970-01-01T00:00:00.000+0100\"}}"
+    );
+    assertMapObjectInvalid(
+      "{\"type\":\"Feature\", \"geometry\":{}, \"properties\":{\"key\":\"a\", \"package\":\"b\", \"value\":\"c\", " +
+      "\"first_seen_at\":\"1970-01-01T00:00:00.000+0100\", \"last_seen_at\":\"2000-12-31T23:59:59.999Z\"}}"
+    );
+    assertMapObjectInvalid(
+      "{\"type\":\"Feature\", \"geometry\":{}, \"properties\":{\"key\":\"a\", \"package\":\"b\", \"value\":\"c\", " +
+      "\"first_seen_at\":\"1970-01-01T00:00:00.000+0100\", \"last_seen_at\":\"2000-12-31T23:59:59.999Z\", " +
+      "\"updated_at\": \"1970-01-01T00:00:00.000Z\"}}"
+    );
+  }
+
+  private static void assertMapObjectInvalid(String json) {
+    assertNull(JsonMapObjectDecoder.decodeMapObject(
+      Json.createReader(new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8))).readObject()
+    ));
+  }
+
+  @Test
+  public void testUtilityClass() {
+    TestUtil.testUtilityClass(JsonMapObjectDecoder.class);
+  }
+}
Index: applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonSequencesDecoderTest.java
===================================================================
--- applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonSequencesDecoderTest.java	(revision 34317)
+++ applications/editors/josm/plugins/MicrosoftStreetside/test/unit/org/openstreetmap/josm/plugins/streetside/utils/api/JsonSequencesDecoderTest.java	(revision 34317)
@@ -0,0 +1,219 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.streetside.utils.api;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.openstreetmap.josm.plugins.streetside.utils.api.JsonDecoderTest.assertDecodesToNull;
+
+import java.io.ByteArrayInputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.function.Function;
+
+import javax.json.Json;
+import javax.json.JsonArray;
+import javax.json.JsonObject;
+import javax.json.JsonValue;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.streetside.StreetsideImage;
+import org.openstreetmap.josm.plugins.streetside.StreetsideSequence;
+import org.openstreetmap.josm.plugins.streetside.utils.JsonUtil;
+import org.openstreetmap.josm.plugins.streetside.utils.TestUtil;
+
+public class JsonSequencesDecoderTest {
+
+
+  @Ignore
+  @Test
+  public void testDecodeSequences() {
+    Collection<StreetsideSequence> exampleSequences = JsonDecoder.decodeFeatureCollection(
+      Json.createReader(this.getClass().getResourceAsStream("/api/v3/responses/searchSequences.json")).readObject(),
+      JsonSequencesDecoder::decodeSequence
+    );
+    assertNotNull(exampleSequences);
+    assertEquals(1, exampleSequences.size());
+    StreetsideSequence seq = exampleSequences.iterator().next();
+    assertEquals(4, seq.getImages().size());
+
+    assertEquals("LwrHXqFRN_pszCopTKHF_Q", ((StreetsideImage) seq.getImages().get(0)).getId());
+    assertEquals("Aufjv2hdCKwg9LySWWVSwg", ((StreetsideImage) seq.getImages().get(1)).getId());
+    assertEquals("QEVZ1tp-PmrwtqhSwdW9fQ", ((StreetsideImage) seq.getImages().get(2)).getId());
+    assertEquals("G_SIwxNcioYeutZuA8Rurw", ((StreetsideImage) seq.getImages().get(3)).getId());
+
+    assertEquals(323.0319999999999, seq.getImages().get(0).getHe(), 1e-10);
+    assertEquals(320.8918, seq.getImages().get(1).getHe(), 1e-10);
+    assertEquals(333.62239999999997, seq.getImages().get(2).getHe(), 1e-10);
+    assertEquals(329.94820000000004, seq.getImages().get(3).getHe(), 1e-10);
+
+    assertEquals(new LatLon(7.246497, 16.432958),  seq.getImages().get(0).getLatLon());
+    assertEquals(new LatLon(7.246567, 16.432955),  seq.getImages().get(1).getLatLon());
+    assertEquals(new LatLon(7.248372, 16.432971),  seq.getImages().get(2).getLatLon());
+    assertEquals(new LatLon(7.249027, 16.432976),  seq.getImages().get(3).getLatLon());
+
+    assertEquals(1_457_963_093_860L, seq.getCd()); // 2016-03-14T13:44:53.860 UTC
+  }
+
+  @Test
+  public void testDecodeSequencesInvalid() {
+    // null input
+    assertEquals(0, JsonDecoder.decodeFeatureCollection(null, JsonSequencesDecoder::decodeSequence).size());
+    // empty object
+    assertNumberOfDecodedSequences(0, "{}");
+    // object without type=FeatureCollection
+    assertNumberOfDecodedSequences(0, "{\"features\": []}");
+    // object with wrong value for the type attribute
+    assertNumberOfDecodedSequences(0, "{\"type\": \"SomethingArbitrary\", \"features\": []}");
+    // object without features-array
+    assertNumberOfDecodedSequences(0, "{\"type\": \"FeatureCollection\"}");
+    // object with a value for the features-key, but wrong type (in this case string instead of Array)
+    assertNumberOfDecodedSequences(0, "{\"type\": \"FeatureCollection\", \"features\": \"notAnArray\"}");
+  }
+
+  @Test
+  public void testDecodeSequencesWithArbitraryObjectAsFeature() {
+    assertNumberOfDecodedSequences(0, "{\"type\": \"FeatureCollection\", \"features\": [{}]}");
+  }
+
+  private static void assertNumberOfDecodedSequences(int expectedNumberOfSequences, String jsonString) {
+    assertEquals(
+      expectedNumberOfSequences,
+      JsonDecoder.decodeFeatureCollection(
+        Json.createReader(new ByteArrayInputStream(jsonString.getBytes(StandardCharsets.UTF_8))).readObject(),
+        JsonSequencesDecoder::decodeSequence
+      ).size()
+    );
+  }
+
+  @Ignore
+  @Test
+  public void testDecodeSequence() {
+    StreetsideSequence exampleSequence = JsonSequencesDecoder.decodeSequence(
+      Json.createReader(this.getClass().getResourceAsStream("/api/v3/responses/sequence.json")).readObject()
+    );
+    assertEquals("cHBf9e8n0pG8O0ZVQHGFBQ", exampleSequence.getId());
+    assertEquals(1_457_963_077_206L, exampleSequence.getCd()); // 2016-03-14T13:44:37.206 UTC
+    assertEquals(2, exampleSequence.getImages().size());
+
+    assertEquals(
+      new StreetsideImage("76P0YUrlDD_lF6J7Od3yoA", new LatLon(16.43279, 7.246085), 96.71454),
+      exampleSequence.getImages().get(0)
+    );
+    assertEquals(
+      new StreetsideImage("Ap_8E0BwoAqqewhJaEbFyQ", new LatLon(16.432799, 7.246082), 96.47705000000002),
+      exampleSequence.getImages().get(1)
+    );
+  }
+
+  @Test
+  public void testDecodeSequenceInvalid() {
+    // null input
+    assertNull(JsonSequencesDecoder.decodeSequence(null));
+    // `properties` key is not set
+    assertDecodesToNull(JsonSequencesDecoder::decodeSequence, "{\"type\": \"Feature\"}");
+    // value for the key `key` in the properties is missing
+    assertDecodesToNull(JsonSequencesDecoder::decodeSequence,
+      "{\"type\": \"Feature\", \"properties\": {}}"
+    );
+    // value for the key `user_key` in the properties is missing
+    assertDecodesToNull(
+      JsonSequencesDecoder::decodeSequence,
+      "{\"type\": \"Feature\", \"properties\": {\"key\": \"someKey\"}}"
+    );
+    // value for the key `captured_at` in the properties is missing
+    assertDecodesToNull(
+      JsonSequencesDecoder::decodeSequence,
+      "{\"type\": \"Feature\", \"properties\": {\"key\": \"someKey\", \"user_key\": \"arbitraryUserKey\"}}"
+    );
+    // the date in `captured_at` has an unrecognized format
+    assertDecodesToNull(
+      JsonSequencesDecoder::decodeSequence,
+      "{\"type\": \"Feature\", \"properties\": {\"key\": \"someKey\", \"captured_at\": \"unrecognizedDateFormat\"}}"
+    );
+    // the `image_key` array and the `cas` array contain unexpected values (in this case `null`)
+    assertDecodesToNull(
+      JsonSequencesDecoder::decodeSequence,
+      "{\"type\": \"Feature\", \"properties\": {\"key\": \"someKey\", \"user_key\": \"arbitraryUserKey\",",
+      "\"captured_at\": \"1970-01-01T00:00:00.000Z\",",
+      "\"coordinateProperties\": {\"cas\": [null, null, null, null, 1.0, 1.0, 1.0],",
+      "\"image_keys\": [null, null, \"key\", \"key\", null, null, \"key\"]}},",
+      "\"geometry\": {\"type\": \"LineString\", \"coordinates\": [null, [1,1], null, [1,1], null, [1,1], null]}}"
+    );
+  }
+
+  /**
+   * Checks if an empty array is returned, if <code>null</code> is supplied to the method as the array.
+   */
+  @Test
+  public void testDecodeJsonArray()
+      throws NoSuchMethodException, SecurityException, IllegalAccessException,
+      IllegalArgumentException, InvocationTargetException {
+    Method method = JsonSequencesDecoder.class.getDeclaredMethod("decodeJsonArray", JsonArray.class, Function.class, Class.class);
+    method.setAccessible(true);
+    assertEquals(
+      0,
+      ((String[]) method.invoke(null, null, (Function<JsonValue, String>) val -> null, String.class)).length
+    );
+  }
+
+  @Test
+  public void testDecodeCoordinateProperty() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+    Method decodeCoordinateProperty = JsonSequencesDecoder.class.getDeclaredMethod(
+      "decodeCoordinateProperty",
+      JsonObject.class,
+      String.class,
+      Function.class,
+      Class.class
+    );
+    decodeCoordinateProperty.setAccessible(true);
+
+    assertEquals(
+      0,
+      ((String[]) decodeCoordinateProperty.invoke(
+        null, null, "key", (Function<JsonValue, String>) val -> "string", String.class
+      )).length
+    );
+
+    assertEquals(
+      0,
+      ((String[]) decodeCoordinateProperty.invoke(
+        null, JsonUtil.string2jsonObject("{\"coordinateProperties\":{\"key\":0}}"), "key", (Function<JsonValue, String>) val -> "string", String.class
+      )).length
+    );
+  }
+
+  @Test
+  public void testDecodeLatLons()
+      throws NoSuchMethodException, SecurityException, IllegalAccessException,
+      IllegalArgumentException, InvocationTargetException {
+    Method decodeLatLons = JsonSequencesDecoder.class.getDeclaredMethod("decodeLatLons", JsonObject.class);
+    decodeLatLons.setAccessible(true);
+
+    assertEquals(0, ((LatLon[]) decodeLatLons.invoke(null, (JsonObject) null)).length);
+    assertEquals(0, ((LatLon[]) decodeLatLons.invoke(null, JsonUtil.string2jsonObject("{\"coordinates\":0}"))).length);
+    assertEquals(0, ((LatLon[]) decodeLatLons.invoke(null, JsonUtil.string2jsonObject("{\"coordinates\":[]}"))).length);
+
+    assertEquals(0, ((LatLon[]) decodeLatLons.invoke(null, Json.createReader(new ByteArrayInputStream(
+      "{\"type\": \"Feature\", \"coordinates\": []}".getBytes(StandardCharsets.UTF_8)
+    )).readObject())).length);
+
+    LatLon[] example = (LatLon[]) decodeLatLons.invoke(null, Json.createReader(new ByteArrayInputStream(
+      "{\"type\": \"LineString\", \"coordinates\": [ [1,2,3], [\"a\", 2], [1, \"b\"] ]}".getBytes(StandardCharsets.UTF_8)
+    )).readObject());
+    assertEquals(3, example.length);
+    assertNull(example[0]);
+    assertNull(example[1]);
+    assertNull(example[2]);
+  }
+
+  @Test
+  public void testUtilityClass() {
+    TestUtil.testUtilityClass(JsonSequencesDecoder.class);
+  }
+
+}
